ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary - #1012

Closed
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634
Closed

ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinary#1012
alphalfalfa wants to merge 3 commits into
apache:masterfrom
alphalfalfa:arrow-633-634

Conversation

@alphalfalfa

Copy link
Copy Markdown
Contributor

The changes include:

  • Arrow-633: [Java] Add support for FixedWidthBinary type
  • Arrow-634: Add integration tests for FixedSizeBinary
  • Fixed a bug of integration test suite that primitive case with non-zero batch sizes was ignored

I also commented on changes that needs more review.

fields.append(get_field(type_ + "_nonnullable", type_, False))

return _generate_file("primitive", fields, batch_sizes)
name = "primitive"

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added name suffix for primitive case such that primitive test case at line 823/824 become both effective. Previously the first one was overwritten by the second one and hence ignored.

]
},
{
major: "Fixed",

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixedSizeBinary has a variable width, I am not sure what integer value to put here. I went ahead and put -1 to mark it as a special case. This changes also leads to quite some changes of if statements in the codegen template FixedValueVectors.java.

@icexellossicexellossAug 31, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this change. FixValueVectors have static type width that is specified in ValueVectorTypes.tdd. Having type width to be dynamic would complicated the template and result in inconsistency in the resulting classes.

Is there a reason FixedSizeBinary needs to have dynamic type witdh? i.e., can we have byteWitdh = 1 and use the type width in the Schema to retrieve and store values? This would simplify things.

cc @wesm

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bottom line is that FixedSizeBinaryVector class should have a way to access the information about the dynamic type width. The only way I found is by changing the static type width in the class to non-static and initialize in the constructor. Did I miss a better way to pass the information? I don't like to put a lot of if/elseif/else statements in a codegen template either :)

Regarding the value being set to a positive integer like 1, it is highly misleading for readers in my opinion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Yeah byteWidth = 1 wouldn't work because of how the template works. But I think we should still have typeBitWidth = 8 in the type layout in the schema to match Binary type.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@icexelloss, the VarBinary type has a width of 4 (instead of 8) which make sense because each element has a 4-byte offset. Do you think it is better to use 4 as well? Btw, VarBinary is using a different template.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset is 4 bytes wide. Data width is 1 byte wide.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am talking about the type layout in the schema. Not the constant in the vector class. Sorry for the confusion.

@jacques-njacques-nSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably refactor the templates some before introducing this change. In reality, I'd like to propose that we rework the vector hierarchy entirely and work much more like ArrowBuf and it's related parents work. In that case, we just grab a memory address and bypass all the object hierarchy for high performance methods but still use superclass delegation for non-performance critical methods.

For the ValueVector hierarchy/codegen situation, let's implement two classes:

BaseFixedVector (would take a dynamic size variable)
BaseVariableVector

These would both be non-code generated classes. Then we could generate code generated subclasses of these that only implement methods that need code generation for performance. Most of these methods would probably appear as custom methods in mutator/accessors.

Then, the changes for a new Custom fixed width vector would just be specializations of the BaseFixedWidthVector called something like FixedBinaryVector and FixedVarcharVector and in those specialization, the width in the mutators and accessors could come from a instance variable instead of a constant.

I believe this would allow us to simplify the codebase and make maintenance of the base classes much easier.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good to me. I'll wait for the refactoring to complete and come back to modify this PR

if (valueCount == 0) {
return 0;
}
return valueCount * ${type.width};

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since FixedSizeBinary does not have a static type.width, I replaced all ${type.width} to TYPE_WIDTH.

}

public void set(int index, ArrowBuf buffer){
assert TYPE_WIDTH <= buffer.capacity();

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to validate an input of ArrowBuf type?

return VALUES_64;
default:
throw new IllegalArgumentException("only 8, 16, 32, or 64 bits supported");
return new VectorLayout(DATA, typeBitWidth);

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing C++ implemetation allows any typeBitWidth, I followed and remove this exception. Is this correct?

@alphalfalfaalphalfalfa changed the title WIP: ARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryARROW-633/ARROW-634: Add Java support and integration test for FixedSizeBinaryAug 30, 2017
}

@Override
public TypeLayout visit(ArrowType.FixedSizeBinary type) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be newVariableWidthTypeLayout() to be consistent with Binary type?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should still be FixedWidthTypeLayout because each element is fixed-size and no offset vector is necessary

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the data type width should be 8-bit instead of type.getByteWidth() * 8.

VarBinary has 8-bit data type width and FixedBinary should be the same.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I read more of the doc, I am not too sure.

https://github.com/apache/arrow/blob/master/format/Schema.fbs#L225

@wesm, can you clarify the what the correct bit_width in the vector layout should be?

ByteArrayOutputStream stream = new ByteArrayOutputStream();
final int numValues = 10;
final int typeWidth = 11;
byte[][] byteValues = new byte[numValues][typeWidth];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix the style of this?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I assume you mean the spacing if the for loop, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@elahrvivaz

Copy link
Copy Markdown
Contributor

lgtm

wesm
wesm approved these changes Sep 4, 2017

@wesmwesm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, @jacques-n can you have a look?

@wesm

wesm commented Sep 4, 2017

Copy link
Copy Markdown
Member

@alphalfalfa can you rebase?

* ${minor.class} implements a vector of fixed width values. Elements in the vector are accessed
* by position, starting from the logical start of the vector. Values should be pushed onto the
* vector sequentially, but may be randomly accessed.
<#if (type.width > 0) >

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to minimize the if else statement in the template to simply. I prefer we remove this if else here and state something like:

The width of each element is defined in getWidth()

<#if (type.width < 0)>
public final int TYPE_WIDTH;
<#else>
public static final int TYPE_WIDTH = ${type.width};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about having TYPE_WIDTH defined as static in some classes and non static in others.

I think it's cleaner if we define TYPE_WIDTH only as static and define another class method getTypeWidth()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason is all caps are usually used to define static constant. Type width for fixed binary is not constant. so I think it's cleaner to not reuse the same variable for fixed binary.

<#if (type.width < 0 || type.width > 8 || minor.class == "IntervalDay")>
public ${minor.javaType!type.javaType} get(int index) {
return data.slice(index * ${type.width}, ${type.width});
<#if (minor.class == "FixedSizeBinary")>

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner if we get FixedSizeBinary into it's top level:

<#if (type.width) < 0 && minor.class == "FixedSizeBinary">
public ${minor.javaType!type.javaType} get(int index) {
...
}
</#if>

Since it doesn't share logic with the original get method

* ${minor.class}.Mutator implements a mutable vector of fixed width values. Elements in the
* vector are accessed by position from the logical start of the vector. Values should be pushed
* onto the vector sequentially, but may be randomly accessed.
<#if (type.width > 0)>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. I prefer we don't have the if else here.


<#assign fields = minor.fields!type.fields />
public void set(int index, int isSet<#list fields as field>, ${field.type} ${field.name}Field</#list> ){
public void set(int index, int isSet<#list fields as field><#if field.include!true >, ${field.type} ${field.name}Field</#if></#list> ){

@icexellossicexellossSep 5, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing, can you explain this logic? Seems you added field.include = false just for FixedBinaryVector, why?

* @param value array of bytes (or int if smaller than 4 bytes) to write
*/
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {
public void set(int index, <#if type.major == "VarLen">byte[]<#elseif (type.width >= 0 && type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is not:

public void set(int index, <#if type.major == "VarLen" && minor.class == "FixedSizeBinary">byte[]<#elseif (type.width < 4)>int<#else>${minor.javaType!type.javaType}</#if> value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm, the java type for fixed size binary is byte[] so this would be equivalent.

}

<#elseif minor.class == "FixedSizeBinary">
public void set(int index, ${minor.class}Holder holder){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These set methods looks similar to the existing ones, why do we need to have special code gen for these?

wesm pushed a commit that referenced this pull request Feb 7, 2018
…tion tests (Updated)
The original PR is at #1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closes#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
@alphalfalfa
alphalfalfa deleted the arrow-633-634 branch February 8, 2018 22:27
pribor pushed a commit to GlobalWebIndex/arrow that referenced this pull request Oct 24, 2025
…tion tests (Updated)
The original PR is at apache#1012. Due to the major refactoring last year, changes are big. So I created this separate PR for easier to review and will cancel the other one later.
Changes include:
* Arrow-633: [Java] Add support for FixedWidthBinary type
* Arrow-634: Add integration tests for FixedSizeBinary
Author: Jingyuan Wang <jingyuan@live.com>
Author: jingyuan <jingyuan.nt@gmail.com>
Closesapache#1492 from alphalfalfa/updated-arrow-633-634 and squashes the following commits:
c994a19 [jingyuan] create data buffer layout for FixedSizeBinary directly instead of using dataBuffer() method and some other changes based on PR comments
873c5b2 [jingyuan] do not pass scale or byteWidth into writeValueToGenerator in JsonFileWriter.java
4fbb67d [jingyuan] put arbitrary values for FixSizeBinary nulls
0c0015d [Jingyuan Wang] add a new line
a8a9553 [Jingyuan Wang] Pass byteWidth info for FixedSizeBinary type in JsonFileReader
1a64c5c [Jingyuan Wang] expand get() method inside getObject() method to remove duplicate check of isSet()
071fb25 [Jingyuan Wang] ARROW-633/634: Add FixedSizeBinary support in Java and integration tests
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@alphalfalfa@elahrvivaz@wesm@jacques-n@icexelloss