[
https://issues.apache.org/jira/browse/CALCITE-3498?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Feng Zhu updated CALCITE-3498:
------------------------------
Description:
Current now, the compution of unnest operation's ordinality is conducted in
*_current()_* method (
[https://github.com/apache/calcite/blob/3853118b4d1d48f7d3970b5488baf7ca78d5028e/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java#L2764).]
Consequently, when the method is called, the ordinality will be incremented,
leading to incorrect and un-deterministic result.
We can use a simple query for illustration.
{code:java}
Query:
==============================================================
select v, o
from unnest(array[100,200]) with ordinality as t1(v, o)
where v > 1
Expected Result
==============================================================
V=100; O=1
V=200; O=2
{code}
However, we get the follow incorrect result.
{code:java}
V=100; O=2
V=200; O=4
{code}
We can infer to the code generated. It can be seen that
*inputEnumerator.current()* has been called two times, one for filter (v>1) and
one for select (v, o).
{code:java}
public org.apache.calcite.linq4j.Enumerable bind(final
org.apache.calcite.DataContext root) {
final org.apache.calcite.linq4j.Enumerable _inputEnumerable = ..............
final org.apache.calcite.linq4j.Enumerable _inputEnumerable0 =
child.selectMany(org.apache.calcite.runtime.SqlFunctions.flatProduct(new int[] {
-1}, true, new
org.apache.calcite.runtime.SqlFunctions.FlatProductInputType[] {
org.apache.calcite.runtime.SqlFunctions.FlatProductInputType.SCALAR}));
return new org.apache.calcite.linq4j.AbstractEnumerable(){
public org.apache.calcite.linq4j.Enumerator enumerator() {
return new org.apache.calcite.linq4j.Enumerator(){
public final org.apache.calcite.linq4j.Enumerator inputEnumerator =
_inputEnumerable0.enumerator();
public void reset() {
inputEnumerator.reset();
} public boolean moveNext() {
while (inputEnumerator.moveNext()) {
if
(org.apache.calcite.runtime.SqlFunctions.toInt(((org.apache.calcite.runtime.FlatLists.ComparableList)
inputEnumerator.current()).get(0)) > 1) {
return true;
}
}
return false;
} public void close() {
inputEnumerator.close();
} public Object current() {
final org.apache.calcite.runtime.FlatLists.ComparableList current
= (org.apache.calcite.runtime.FlatLists.ComparableList)
inputEnumerator.current();
return new Object[] {
current.get(0),
current.get(1)};
} };
} };
}
public Class getElementType() {
return java.lang.Object[].class;
}
{code}
was:
Current now, the compution of unnest operation's ordinality is conducted in
*_current()_* method (
[https://github.com/apache/calcite/blob/3853118b4d1d48f7d3970b5488baf7ca78d5028e/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java#L2764).]
Consequently, when the method is called, the ordinality will be incremented,
leading to incorrect and un-deterministic result.
We use a simple query for illustration.
{code:java}
Query:
==============================================================
select v, o
from unnest(array[100,200]) with ordinality as t1(v, o)
where v > 1
Expected Result
==============================================================
V=100; O=1
V=200; O=2
{code}
However, we get the follow incorrect result.
{code:java}
V=100; O=2
V=200; O=4
{code}
We can infer to the code generated. It can be seen that
*inputEnumerator.current()* has been called two times, one for filter (v>1) and
one for select (v, o).
{code:java}
public org.apache.calcite.linq4j.Enumerable bind(final
org.apache.calcite.DataContext root) {
final org.apache.calcite.linq4j.Enumerable _inputEnumerable = ..............
final org.apache.calcite.linq4j.Enumerable _inputEnumerable0 =
child.selectMany(org.apache.calcite.runtime.SqlFunctions.flatProduct(new int[] {
-1}, true, new
org.apache.calcite.runtime.SqlFunctions.FlatProductInputType[] {
org.apache.calcite.runtime.SqlFunctions.FlatProductInputType.SCALAR}));
return new org.apache.calcite.linq4j.AbstractEnumerable(){
public org.apache.calcite.linq4j.Enumerator enumerator() {
return new org.apache.calcite.linq4j.Enumerator(){
public final org.apache.calcite.linq4j.Enumerator inputEnumerator =
_inputEnumerable0.enumerator();
public void reset() {
inputEnumerator.reset();
} public boolean moveNext() {
while (inputEnumerator.moveNext()) {
if
(org.apache.calcite.runtime.SqlFunctions.toInt(((org.apache.calcite.runtime.FlatLists.ComparableList)
inputEnumerator.current()).get(0)) > 1) {
return true;
}
}
return false;
} public void close() {
inputEnumerator.close();
} public Object current() {
final org.apache.calcite.runtime.FlatLists.ComparableList current
= (org.apache.calcite.runtime.FlatLists.ComparableList)
inputEnumerator.current();
return new Object[] {
current.get(0),
current.get(1)};
} };
} };
}
public Class getElementType() {
return java.lang.Object[].class;
}
{code}
> Unnest operation's ordinality should be deterministic
> -----------------------------------------------------
>
> Key: CALCITE-3498
> URL: https://issues.apache.org/jira/browse/CALCITE-3498
> Project: Calcite
> Issue Type: Bug
> Components: core
> Affects Versions: 1.21.0
> Environment: **_**_**
> Reporter: Feng Zhu
> Assignee: Feng Zhu
> Priority: Major
>
> Current now, the compution of unnest operation's ordinality is conducted in
> *_current()_* method (
> [https://github.com/apache/calcite/blob/3853118b4d1d48f7d3970b5488baf7ca78d5028e/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java#L2764).]
> Consequently, when the method is called, the ordinality will be incremented,
> leading to incorrect and un-deterministic result.
> We can use a simple query for illustration.
> {code:java}
> Query:
> ==============================================================
> select v, o
> from unnest(array[100,200]) with ordinality as t1(v, o)
> where v > 1
> Expected Result
> ==============================================================
> V=100; O=1
> V=200; O=2
> {code}
> However, we get the follow incorrect result.
> {code:java}
> V=100; O=2
> V=200; O=4
> {code}
> We can infer to the code generated. It can be seen that
> *inputEnumerator.current()* has been called two times, one for filter (v>1)
> and one for select (v, o).
> {code:java}
> public org.apache.calcite.linq4j.Enumerable bind(final
> org.apache.calcite.DataContext root) {
> final org.apache.calcite.linq4j.Enumerable _inputEnumerable = ..............
> final org.apache.calcite.linq4j.Enumerable _inputEnumerable0 =
> child.selectMany(org.apache.calcite.runtime.SqlFunctions.flatProduct(new
> int[] {
> -1}, true, new
> org.apache.calcite.runtime.SqlFunctions.FlatProductInputType[] {
> org.apache.calcite.runtime.SqlFunctions.FlatProductInputType.SCALAR}));
> return new org.apache.calcite.linq4j.AbstractEnumerable(){
> public org.apache.calcite.linq4j.Enumerator enumerator() {
> return new org.apache.calcite.linq4j.Enumerator(){
> public final org.apache.calcite.linq4j.Enumerator inputEnumerator
> = _inputEnumerable0.enumerator();
> public void reset() {
> inputEnumerator.reset();
> } public boolean moveNext() {
> while (inputEnumerator.moveNext()) {
> if
> (org.apache.calcite.runtime.SqlFunctions.toInt(((org.apache.calcite.runtime.FlatLists.ComparableList)
> inputEnumerator.current()).get(0)) > 1) {
> return true;
> }
> }
> return false;
> } public void close() {
> inputEnumerator.close();
> } public Object current() {
> final org.apache.calcite.runtime.FlatLists.ComparableList
> current = (org.apache.calcite.runtime.FlatLists.ComparableList)
> inputEnumerator.current();
> return new Object[] {
> current.get(0),
> current.get(1)};
> } };
> } };
> }
> public Class getElementType() {
> return java.lang.Object[].class;
> }
> {code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)