Skip to content

Commit ca3aff4

Browse files
committed
[SQL] Fix incorrect conversion of long intervals to integers
Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
1 parent 95428f7 commit ca3aff4

File tree

7 files changed

+136
-162
lines changed

7 files changed

+136
-162
lines changed

crates/sqllib/src/casts.rs

Lines changed: 47 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,212 +1739,103 @@ pub fn cast_to_i64_Weight(w: Weight) -> SqlResult<i64> {
17391739
}
17401740

17411741
#[doc(hidden)]
1742-
pub fn cast_to_i8_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<i8> {
1743-
cast_to_i8_i64(value.milliseconds())
1742+
pub fn cast_to_i8_LongInterval_YEARS(value: LongInterval) -> SqlResult<i8> {
1743+
cast_to_i8_i32(value.years())
17441744
}
17451745

17461746
#[doc(hidden)]
1747-
pub fn cast_to_i16_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<i16> {
1748-
cast_to_i16_i64(value.milliseconds())
1747+
pub fn cast_to_i8_LongInterval_MONTHS(value: LongInterval) -> SqlResult<i8> {
1748+
cast_to_i8_i32(value.months())
17491749
}
17501750

17511751
#[doc(hidden)]
1752-
pub fn cast_to_i32_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<i32> {
1753-
cast_to_i32_i64(value.milliseconds())
1752+
pub fn cast_to_i16_LongInterval_YEARS(value: LongInterval) -> SqlResult<i16> {
1753+
cast_to_i16_i32(value.years())
17541754
}
17551755

17561756
#[doc(hidden)]
1757-
pub fn cast_to_i64_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<i64> {
1758-
Ok(value.milliseconds())
1759-
}
1760-
1761-
#[doc(hidden)]
1762-
pub fn cast_to_i8_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<i8> {
1763-
cast_to_i8_i64(value.milliseconds())
1764-
}
1765-
1766-
#[doc(hidden)]
1767-
pub fn cast_to_i16_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<i16> {
1768-
cast_to_i16_i64(value.milliseconds())
1769-
}
1770-
1771-
#[doc(hidden)]
1772-
pub fn cast_to_i32_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<i32> {
1773-
cast_to_i32_i64(value.milliseconds())
1774-
}
1775-
1776-
#[doc(hidden)]
1777-
pub fn cast_to_i64_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<i64> {
1778-
Ok(value.milliseconds())
1779-
}
1780-
1781-
#[doc(hidden)]
1782-
pub fn cast_to_i8_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<i8> {
1783-
cast_to_i8_i64(value.milliseconds())
1784-
}
1785-
1786-
#[doc(hidden)]
1787-
pub fn cast_to_i16_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<i16> {
1788-
cast_to_i16_i64(value.milliseconds())
1789-
}
1790-
1791-
#[doc(hidden)]
1792-
pub fn cast_to_i32_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<i32> {
1793-
cast_to_i32_i64(value.milliseconds())
1794-
}
1795-
1796-
#[doc(hidden)]
1797-
pub fn cast_to_i64_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<i64> {
1798-
Ok(value.milliseconds())
1799-
}
1800-
1801-
#[doc(hidden)]
1802-
pub fn cast_to_i8_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<i8> {
1803-
cast_to_i8_i64(value.milliseconds())
1804-
}
1805-
1806-
#[doc(hidden)]
1807-
pub fn cast_to_i16_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<i16> {
1808-
cast_to_i16_i64(value.milliseconds())
1809-
}
1810-
1811-
#[doc(hidden)]
1812-
pub fn cast_to_i32_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<i32> {
1813-
cast_to_i32_i64(value.milliseconds())
1814-
}
1815-
1816-
#[doc(hidden)]
1817-
pub fn cast_to_i64_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<i64> {
1818-
Ok(value.milliseconds())
1819-
}
1820-
1821-
#[doc(hidden)]
1822-
pub fn cast_to_u8_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<u8> {
1823-
cast_to_u8_i64(value.milliseconds())
1824-
}
1825-
1826-
#[doc(hidden)]
1827-
pub fn cast_to_u16_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<u16> {
1828-
cast_to_u16_i64(value.milliseconds())
1829-
}
1830-
1831-
#[doc(hidden)]
1832-
pub fn cast_to_u32_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<u32> {
1833-
cast_to_u32_i64(value.milliseconds())
1834-
}
1835-
1836-
#[doc(hidden)]
1837-
pub fn cast_to_u64_ShortInterval_DAYS(value: ShortInterval) -> SqlResult<u64> {
1838-
cast_to_u64_i64(value.milliseconds())
1757+
pub fn cast_to_i16_LongInterval_MONTHS(value: LongInterval) -> SqlResult<i16> {
1758+
cast_to_i16_i32(value.months())
18391759
}
18401760

18411761
#[doc(hidden)]
1842-
pub fn cast_to_u8_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<u8> {
1843-
cast_to_u8_i64(value.milliseconds())
1762+
pub fn cast_to_i32_LongInterval_YEARS(value: LongInterval) -> SqlResult<i32> {
1763+
Ok(value.years())
18441764
}
18451765

18461766
#[doc(hidden)]
1847-
pub fn cast_to_u16_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<u16> {
1848-
cast_to_u16_i64(value.milliseconds())
1767+
pub fn cast_to_i32_LongInterval_MONTHS(value: LongInterval) -> SqlResult<i32> {
1768+
Ok(value.months())
18491769
}
18501770

18511771
#[doc(hidden)]
1852-
pub fn cast_to_u32_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<u32> {
1853-
cast_to_u32_i64(value.milliseconds())
1854-
}
1855-
1856-
#[doc(hidden)]
1857-
pub fn cast_to_u64_ShortInterval_HOURS(value: ShortInterval) -> SqlResult<u64> {
1858-
cast_to_u64_i64(value.milliseconds())
1859-
}
1860-
1861-
#[doc(hidden)]
1862-
pub fn cast_to_u8_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<u8> {
1863-
cast_to_u8_i64(value.milliseconds())
1772+
pub fn cast_to_i64_LongInterval_YEARS(value: LongInterval) -> SqlResult<i64> {
1773+
Ok(value.years() as i64)
18641774
}
18651775

18661776
#[doc(hidden)]
1867-
pub fn cast_to_u16_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<u16> {
1868-
cast_to_u16_i64(value.milliseconds())
1777+
pub fn cast_to_i64_LongInterval_MONTHS(value: LongInterval) -> SqlResult<i64> {
1778+
Ok(value.months() as i64)
18691779
}
18701780

18711781
#[doc(hidden)]
1872-
pub fn cast_to_u32_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<u32> {
1873-
cast_to_u32_i64(value.milliseconds())
1782+
pub fn cast_to_u8_LongInterval_YEARS(value: LongInterval) -> SqlResult<u8> {
1783+
cast_to_u8_i32(value.years())
18741784
}
18751785

18761786
#[doc(hidden)]
1877-
pub fn cast_to_u64_ShortInterval_MINUTES(value: ShortInterval) -> SqlResult<u64> {
1878-
cast_to_u64_i64(value.milliseconds())
1787+
pub fn cast_to_u8_LongInterval_MONTHS(value: LongInterval) -> SqlResult<u8> {
1788+
cast_to_u8_i32(value.months())
18791789
}
18801790

18811791
#[doc(hidden)]
1882-
pub fn cast_to_u8_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<u8> {
1883-
cast_to_u8_i64(value.milliseconds())
1792+
pub fn cast_to_u16_LongInterval_YEARS(value: LongInterval) -> SqlResult<u16> {
1793+
cast_to_u16_i32(value.years())
18841794
}
18851795

18861796
#[doc(hidden)]
1887-
pub fn cast_to_u16_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<u16> {
1888-
cast_to_u16_i64(value.milliseconds())
1797+
pub fn cast_to_u16_LongInterval_MONTHS(value: LongInterval) -> SqlResult<u16> {
1798+
cast_to_u16_i32(value.months())
18891799
}
18901800

18911801
#[doc(hidden)]
1892-
pub fn cast_to_u32_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<u32> {
1893-
cast_to_u32_i64(value.milliseconds())
1802+
pub fn cast_to_u32_LongInterval_YEARS(value: LongInterval) -> SqlResult<u32> {
1803+
cast_to_u32_i32(value.years())
18941804
}
18951805

18961806
#[doc(hidden)]
1897-
pub fn cast_to_u64_ShortInterval_SECONDS(value: ShortInterval) -> SqlResult<u64> {
1898-
cast_to_u64_i64(value.milliseconds())
1807+
pub fn cast_to_u32_LongInterval_MONTHS(value: LongInterval) -> SqlResult<u32> {
1808+
cast_to_u32_i32(value.months())
18991809
}
19001810

1901-
cast_function!(i8, i8, ShortInterval_DAYS, ShortInterval);
1902-
cast_function!(i16, i16, ShortInterval_DAYS, ShortInterval);
1903-
cast_function!(i32, i32, ShortInterval_DAYS, ShortInterval);
1904-
cast_function!(i64, i64, ShortInterval_DAYS, ShortInterval);
1905-
cast_function!(i8, i8, ShortInterval_HOURS, ShortInterval);
1906-
cast_function!(i16, i16, ShortInterval_HOURS, ShortInterval);
1907-
cast_function!(i32, i32, ShortInterval_HOURS, ShortInterval);
1908-
cast_function!(i64, i64, ShortInterval_HOURS, ShortInterval);
1909-
cast_function!(i8, i8, ShortInterval_MINUTES, ShortInterval);
1910-
cast_function!(i16, i16, ShortInterval_MINUTES, ShortInterval);
1911-
cast_function!(i32, i32, ShortInterval_MINUTES, ShortInterval);
1912-
cast_function!(i64, i64, ShortInterval_MINUTES, ShortInterval);
1913-
cast_function!(i8, i8, ShortInterval_SECONDS, ShortInterval);
1914-
cast_function!(i16, i16, ShortInterval_SECONDS, ShortInterval);
1915-
cast_function!(i32, i32, ShortInterval_SECONDS, ShortInterval);
1916-
cast_function!(i64, i64, ShortInterval_SECONDS, ShortInterval);
1917-
1918-
cast_function!(u8, u8, ShortInterval_DAYS, ShortInterval);
1919-
cast_function!(u16, u16, ShortInterval_DAYS, ShortInterval);
1920-
cast_function!(u32, u32, ShortInterval_DAYS, ShortInterval);
1921-
cast_function!(u64, u64, ShortInterval_DAYS, ShortInterval);
1922-
cast_function!(u8, u8, ShortInterval_HOURS, ShortInterval);
1923-
cast_function!(u16, u16, ShortInterval_HOURS, ShortInterval);
1924-
cast_function!(u32, u32, ShortInterval_HOURS, ShortInterval);
1925-
cast_function!(u64, u64, ShortInterval_HOURS, ShortInterval);
1926-
cast_function!(u8, u8, ShortInterval_MINUTES, ShortInterval);
1927-
cast_function!(u16, u16, ShortInterval_MINUTES, ShortInterval);
1928-
cast_function!(u32, u32, ShortInterval_MINUTES, ShortInterval);
1929-
cast_function!(u64, u64, ShortInterval_MINUTES, ShortInterval);
1930-
cast_function!(u8, u8, ShortInterval_SECONDS, ShortInterval);
1931-
cast_function!(u16, u16, ShortInterval_SECONDS, ShortInterval);
1932-
cast_function!(u32, u32, ShortInterval_SECONDS, ShortInterval);
1933-
cast_function!(u64, u64, ShortInterval_SECONDS, ShortInterval);
1934-
19351811
#[doc(hidden)]
1936-
pub fn cast_to_i64_LongInterval_YEARS(value: LongInterval) -> SqlResult<i64> {
1937-
Ok(value.months() as i64)
1812+
pub fn cast_to_u64_LongInterval_YEARS(value: LongInterval) -> SqlResult<u64> {
1813+
cast_to_u64_i32(value.years())
19381814
}
19391815

19401816
#[doc(hidden)]
1941-
pub fn cast_to_i64_LongInterval_MONTHS(value: LongInterval) -> SqlResult<i64> {
1942-
Ok(value.months() as i64)
1817+
pub fn cast_to_u64_LongInterval_MONTHS(value: LongInterval) -> SqlResult<u64> {
1818+
cast_to_u64_i32(value.months())
19431819
}
19441820

1821+
cast_function!(i8, i8, LongInterval_MONTHS, LongInterval);
1822+
cast_function!(i8, i8, LongInterval_YEARS, LongInterval);
1823+
cast_function!(i16, i16, LongInterval_MONTHS, LongInterval);
1824+
cast_function!(i16, i16, LongInterval_YEARS, LongInterval);
1825+
cast_function!(i32, i32, LongInterval_MONTHS, LongInterval);
1826+
cast_function!(i32, i32, LongInterval_YEARS, LongInterval);
19451827
cast_function!(i64, i64, LongInterval_MONTHS, LongInterval);
19461828
cast_function!(i64, i64, LongInterval_YEARS, LongInterval);
19471829

1830+
cast_function!(u8, u8, LongInterval_MONTHS, LongInterval);
1831+
cast_function!(u8, u8, LongInterval_YEARS, LongInterval);
1832+
cast_function!(u16, u16, LongInterval_MONTHS, LongInterval);
1833+
cast_function!(u16, u16, LongInterval_YEARS, LongInterval);
1834+
cast_function!(u32, u32, LongInterval_MONTHS, LongInterval);
1835+
cast_function!(u32, u32, LongInterval_YEARS, LongInterval);
1836+
cast_function!(u64, u64, LongInterval_MONTHS, LongInterval);
1837+
cast_function!(u64, u64, LongInterval_YEARS, LongInterval);
1838+
19481839
//////// casts to Short interval
19491840

19501841
#[doc(hidden)]

crates/sqllib/src/interval.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ pub struct ShortInterval {
5353
microseconds: i64,
5454
}
5555

56+
#[doc(hidden)]
57+
pub fn reinterpret_ShortInterval(value: ShortInterval) -> i64 {
58+
value.milliseconds()
59+
}
60+
61+
some_polymorphic_function1!(reinterpret, ShortInterval, ShortInterval, i64);
62+
5663
#[doc(hidden)]
5764
impl<D> ::rkyv::Deserialize<ShortInterval, D> for ArchivedShortInterval
5865
where
@@ -485,6 +492,13 @@ impl LongInterval {
485492
}
486493
}
487494

495+
#[doc(hidden)]
496+
pub fn reinterpret_LongInterval(value: LongInterval) -> i64 {
497+
value.months() as i64
498+
}
499+
500+
some_polymorphic_function1!(reinterpret, LongInterval, LongInterval, i64);
501+
488502
#[doc(hidden)]
489503
pub fn abs_LongInterval(value: LongInterval) -> LongInterval {
490504
LongInterval::from_months(num::abs(value.months))

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/backend/rust/ToRustInnerVisitor.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,17 @@ public VisitDecision preorder(DBSPUnaryExpression expression) {
18761876
this.builder.append(")");
18771877
this.pop(expression);
18781878
return VisitDecision.STOP;
1879+
} else if (expression.opcode == DBSPOpcode.REINTERPRET) {
1880+
DBSPTypeBaseType sourceType = expression.source.getType().to(DBSPTypeBaseType.class);
1881+
this.builder.append(expression.opcode.toString())
1882+
.append("_")
1883+
.append(sourceType.shortName())
1884+
.append(sourceType.nullableSuffix())
1885+
.append("(");
1886+
expression.source.accept(this);
1887+
this.builder.append(")");
1888+
this.pop(expression);
1889+
return VisitDecision.STOP;
18791890
}
18801891
if (expression.source.getType().mayBeNull) {
18811892
this.builder.append("(")

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/compiler/frontend/ExpressionCompiler.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import org.apache.calcite.util.DateString;
4242
import org.apache.calcite.util.TimeString;
4343
import org.apache.calcite.util.TimestampString;
44-
import org.dbsp.sqlCompiler.circuit.operator.DBSPConcreteAsofJoinOperator;
4544
import org.dbsp.sqlCompiler.compiler.DBSPCompiler;
4645
import org.dbsp.sqlCompiler.compiler.ICompilerComponent;
4746
import org.dbsp.sqlCompiler.compiler.errors.BaseCompilerException;
@@ -1061,9 +1060,15 @@ public DBSPExpression visitCall(RexCall call) {
10611060
return makeBinaryExpressions(node, type, DBSPOpcode.BW_OR, ops);
10621061
case BIT_XOR:
10631062
return makeBinaryExpressions(node, type, DBSPOpcode.XOR, ops);
1063+
case REINTERPRET:
1064+
// Calcite only seems to generate this for converting intervals to integers
1065+
if ((!type.is(DBSPTypeInteger.class) || type.to(DBSPTypeInteger.class).getWidth() != 64)
1066+
&& !ops.get(0).getType().is(IsIntervalType.class)) {
1067+
throw new InternalCompilerError("Unexpected cast ", node);
1068+
}
1069+
return new DBSPUnaryExpression(node, type, DBSPOpcode.REINTERPRET, ops.get(0));
10641070
case CAST:
10651071
case SAFE_CAST:
1066-
case REINTERPRET:
10671072
if (!validateCast(ops.get(0).getType(), type, call.op.kind == SqlKind.SAFE_CAST)) {
10681073
throw new CompilationError(call.op.kind + " cannot be used to convert " +
10691074
ops.get(0).getType().asSqlString() +

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/ir/expression/DBSPOpcode.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ public enum DBSPOpcode {
100100
// Same as MAP_CONVERT, except the function applied returns SqlResult, and
101101
// the map function returns None in case any partial result is Error.
102102
MAP_CONVERT_SAFE("map_map_safe", false),
103-
;
103+
// Used to implement Calcite's REINTERPRET casts;
104+
// input is always an interval, output is always i64
105+
REINTERPRET("reinterpret", false);
104106

105107
private final String text;
106108
public final boolean isAggregate;

sql-to-dbsp-compiler/SQL-compiler/src/main/java/org/dbsp/sqlCompiler/ir/expression/DBSPUnaryExpression.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public IIndentStream toString(IIndentStream builder) {
7979
if (this.opcode == DBSPOpcode.DECIMAL_TO_INTEGER ||
8080
this.opcode == DBSPOpcode.INTEGER_TO_DECIMAL ||
8181
this.opcode == DBSPOpcode.SHORT_INTERVAL_TO_INTEGER ||
82-
this.opcode == DBSPOpcode.INTEGER_TO_SHORT_INTERVAL) {
82+
this.opcode == DBSPOpcode.INTEGER_TO_SHORT_INTERVAL ||
83+
this.opcode == DBSPOpcode.REINTERPRET) {
8384
return builder.append(this.opcode.toString())
8485
.append("(")
8586
.append(this.source)

0 commit comments

Comments
 (0)