Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change DATE type encoding to integer #2491

Merged
merged 1 commit into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ private Column<?> convert(@Nullable Object recordValue, String name, DataType da
return recordValue == null
? DateColumn.ofNull(name)
: DateColumn.of(
name,
TimeRelatedColumnEncodingUtils.decodeDate(((Number) recordValue).longValue()));
name, TimeRelatedColumnEncodingUtils.decodeDate(((Number) recordValue).intValue()));
case TIME:
return recordValue == null
? TimeColumn.ofNull(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private Column<?> convert(@Nullable AttributeValue itemValue, String name, DataT
return isNull
? DateColumn.ofNull(name)
: DateColumn.of(
name, TimeRelatedColumnEncodingUtils.decodeDate(Long.parseLong(itemValue.n())));
name, TimeRelatedColumnEncodingUtils.decodeDate(Integer.parseInt(itemValue.n())));
case TIME:
return isNull
? TimeColumn.ofNull(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ public static byte[] toBytes(ByteBuffer src) {
}

static void encodeLong(long value, Order order, ByteBuffer dst) {
dst.put(
mask((byte) ((value >> 56) ^ 0x80), order)); // Flip a sign bit to make it binary comparable
// Flip a sign bit to make it binary comparable
dst.put(mask((byte) ((value >> 56) ^ 0x80), order));
dst.put(mask((byte) (value >> 48), order));
dst.put(mask((byte) (value >> 40), order));
dst.put(mask((byte) (value >> 32), order));
Expand All @@ -122,4 +122,12 @@ static void encodeLong(long value, Order order, ByteBuffer dst) {
dst.put(mask((byte) (value >> 8), order));
dst.put(mask((byte) value, order));
}

static void encodeInt(int value, Order order, ByteBuffer dst) {
// Flip a sign bit to make it binary comparable
dst.put(mask((byte) ((value >> 24) ^ 0x80), order));
dst.put(mask((byte) (value >> 16), order));
dst.put(mask((byte) (value >> 8), order));
dst.put(mask((byte) value, order));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.scalar.db.storage.dynamo.bytes;

import static com.scalar.db.storage.dynamo.bytes.BytesUtils.encodeLong;
import static com.scalar.db.storage.dynamo.bytes.BytesUtils.encodeInt;

import com.scalar.db.api.Scan.Ordering.Order;
import com.scalar.db.io.DateColumn;
Expand All @@ -17,14 +17,14 @@ public class DateBytesEncoder implements BytesEncoder<DateColumn> {
public int encodedLength(DateColumn column, Order order) {
assert column.getValue().isPresent();

return 8;
return 4;
}

@Override
public void encode(DateColumn column, Order order, ByteBuffer dst) {
assert column.getValue().isPresent();

long value = TimeRelatedColumnEncodingUtils.encode(column);
encodeLong(value, order, dst);
int value = TimeRelatedColumnEncodingUtils.encode(column);
encodeInt(value, order, dst);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.scalar.db.storage.dynamo.bytes;

import static com.scalar.db.storage.dynamo.bytes.BytesUtils.mask;
import static com.scalar.db.storage.dynamo.bytes.BytesUtils.encodeInt;

import com.scalar.db.api.Scan.Ordering.Order;
import com.scalar.db.io.IntColumn;
Expand All @@ -22,9 +22,6 @@ public void encode(IntColumn column, Order order, ByteBuffer dst) {
assert !column.hasNullValue();

int v = column.getIntValue();
dst.put(mask((byte) ((v >> 24) ^ 0x80), order)); // Flip a sign bit to make it binary comparable
dst.put(mask((byte) (v >> 16), order));
dst.put(mask((byte) (v >> 8), order));
dst.put(mask((byte) v, order));
encodeInt(v, order, dst);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ public String getDataTypeForEngine(DataType scalarDbDataType) {
case BOOLEAN:
return "BOOLEAN";
case INT:
case DATE:
return "INT";
case BIGINT:
case DATE:
case TIME:
case TIMESTAMP:
case TIMESTAMPTZ:
Expand Down Expand Up @@ -126,8 +126,8 @@ public int getSqlTypes(DataType dataType) {
case BOOLEAN:
return Types.BOOLEAN;
case INT:
return Types.INTEGER;
case DATE:
return Types.INTEGER;
case TIME:
case TIMESTAMP:
case TIMESTAMPTZ:
Expand Down Expand Up @@ -307,7 +307,7 @@ public String tryAddIfNotExistsToCreateIndexSql(String createIndexSql) {
@Override
public DateColumn parseDateColumn(ResultSet resultSet, String columnName) throws SQLException {
return DateColumn.of(
columnName, TimeRelatedColumnEncodingUtils.decodeDate(resultSet.getLong(columnName)));
columnName, TimeRelatedColumnEncodingUtils.decodeDate(resultSet.getInt(columnName)));
}

@Override
Expand All @@ -332,7 +332,7 @@ public TimestampTZColumn parseTimestampTZColumn(ResultSet resultSet, String colu
}

@Override
public RdbEngineTimeTypeStrategy<Long, Long, Long, Long> getTimeTypeStrategy() {
public RdbEngineTimeTypeStrategy<Integer, Long, Long, Long> getTimeTypeStrategy() {
return timeTypeEngine;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
import java.time.LocalTime;
import java.time.OffsetDateTime;

public class RdbEngineTimeTypeSqlite implements RdbEngineTimeTypeStrategy<Long, Long, Long, Long> {
public class RdbEngineTimeTypeSqlite
implements RdbEngineTimeTypeStrategy<Integer, Long, Long, Long> {

@Override
public Long convert(LocalDate date) {
public Integer convert(LocalDate date) {
return TimeRelatedColumnEncodingUtils.encode(date);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@
public final class TimeRelatedColumnEncodingUtils {
private TimeRelatedColumnEncodingUtils() {}

public static long encode(DateColumn column) {
public static int encode(DateColumn column) {
assert column.getDateValue() != null;
return encode(column.getDateValue());
}

public static long encode(LocalDate date) {
return date.toEpochDay();
public static int encode(LocalDate date) {
return Math.toIntExact(date.toEpochDay());
Comment on lines +25 to +26
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Encode DATE value as int instead of long

}

public static LocalDate decodeDate(long epochDay) {
public static LocalDate decodeDate(int epochDay) {
return LocalDate.ofEpochDay(epochDay);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,27 @@ public void encodeDate_ShouldWorkProperly() {
DateColumn column = DateColumn.of("date", LocalDate.of(2023, 10, 1));

// Act
long encoded = TimeRelatedColumnEncodingUtils.encode(column);
int encoded = TimeRelatedColumnEncodingUtils.encode(column);

// Assert
assertThat(encoded).isEqualTo(LocalDate.of(2023, 10, 1).toEpochDay());
}

@Test
public void encodeThenDecodeDate_ShouldPreserveDataIntegrity() {
// Arrange
DateColumn min = DateColumn.of("date", DateColumn.MIN_VALUE);
DateColumn max = DateColumn.of("date", DateColumn.MAX_VALUE);

// Act Assert
assertThat(
TimeRelatedColumnEncodingUtils.decodeDate(TimeRelatedColumnEncodingUtils.encode(min)))
.isEqualTo(min.getDateValue());
assertThat(
TimeRelatedColumnEncodingUtils.decodeDate(TimeRelatedColumnEncodingUtils.encode(max)))
.isEqualTo(max.getDateValue());
}

@Test
public void encodeTime_ShouldWorkProperly() {
// Arrange
Expand All @@ -44,6 +59,21 @@ public void encodeTime_ShouldWorkProperly() {
assertThat(encoded).isEqualTo(LocalTime.of(12, 34, 56, 123_456_000).toNanoOfDay());
}

@Test
public void encodeThenDecodeTime_ShouldPreserveDataIntegrity() {
// Arrange
TimeColumn min = TimeColumn.of("time", TimeColumn.MIN_VALUE);
TimeColumn max = TimeColumn.of("time", TimeColumn.MAX_VALUE);

// Act Assert
assertThat(
TimeRelatedColumnEncodingUtils.decodeTime(TimeRelatedColumnEncodingUtils.encode(min)))
.isEqualTo(min.getTimeValue());
assertThat(
TimeRelatedColumnEncodingUtils.decodeTime(TimeRelatedColumnEncodingUtils.encode(max)))
.isEqualTo(max.getTimeValue());
}

@Test
public void encodeTimestamp_ShouldWorkProperly() {
// Arrange
Expand Down Expand Up @@ -124,7 +154,7 @@ public void encodeTimestampTZ_ShouldWorkProperly() {
public void decodeDate_ShouldWorkProperly() {
// Arrange Act
LocalDate date =
TimeRelatedColumnEncodingUtils.decodeDate(LocalDate.of(2023, 10, 1).toEpochDay());
TimeRelatedColumnEncodingUtils.decodeDate((int) LocalDate.of(2023, 10, 1).toEpochDay());

// Assert
assertThat(date).isEqualTo(LocalDate.of(2023, 10, 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ public void createTableInternal_ForOracle_ShouldCreateTableAndIndexes() throws S
public void createTableInternal_ForSqlite_ShouldCreateTableAndIndexes() throws SQLException {
createTableInternal_ForX_CreateTableAndIndexes(
RdbEngine.SQLITE,
"CREATE TABLE \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c4\" BLOB,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" FLOAT,\"c8\" BIGINT,\"c9\" BIGINT,\"c10\" BIGINT,\"c11\" BIGINT, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))",
"CREATE TABLE \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c4\" BLOB,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" FLOAT,\"c8\" INT,\"c9\" BIGINT,\"c10\" BIGINT,\"c11\" BIGINT, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))",
"CREATE INDEX \"index_my_ns_foo_table_c4\" ON \"my_ns$foo_table\" (\"c4\")",
"CREATE INDEX \"index_my_ns_foo_table_c1\" ON \"my_ns$foo_table\" (\"c1\")");
}
Expand Down Expand Up @@ -655,7 +655,7 @@ public void createTableInternal_IfNotExistsForSqlite_ShouldCreateTableAndIndexes
throws SQLException {
createTableInternal_IfNotExistsForX_createTableAndIndexesIfNotExists(
RdbEngine.SQLITE,
"CREATE TABLE IF NOT EXISTS \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c4\" BLOB,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" FLOAT,\"c8\" BIGINT,\"c9\" BIGINT,\"c10\" BIGINT,\"c11\" BIGINT, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))",
"CREATE TABLE IF NOT EXISTS \"my_ns$foo_table\"(\"c3\" BOOLEAN,\"c1\" TEXT,\"c4\" BLOB,\"c2\" BIGINT,\"c5\" INT,\"c6\" DOUBLE,\"c7\" FLOAT,\"c8\" INT,\"c9\" BIGINT,\"c10\" BIGINT,\"c11\" BIGINT, PRIMARY KEY (\"c3\",\"c1\",\"c4\"))",
"CREATE INDEX IF NOT EXISTS \"index_my_ns_foo_table_c4\" ON \"my_ns$foo_table\" (\"c4\")",
"CREATE INDEX IF NOT EXISTS \"index_my_ns_foo_table_c1\" ON \"my_ns$foo_table\" (\"c1\")");
}
Expand Down