Skip to content

Commit 78f5292

Browse files
authored
support mysql date/datetime (#287)
1 parent b80af97 commit 78f5292

File tree

3 files changed

+297
-2
lines changed

3 files changed

+297
-2
lines changed

src/main/java/com/alipay/oceanbase/rpc/protocol/payload/impl/ObObjType.java

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,12 +1664,130 @@ public ObObjMeta getDefaultObjMeta() {
16641664
public Comparable parseToComparable(Object o, ObCollationType ct) {
16651665
throw new FeatureNotSupportedException("ObBitType is not supported .");
16661666
}
1667-
};
1667+
},
16681668
/*
16691669
ObEnumType(36)
16701670
ObSetType(37)
1671-
ObMaxType // invalid type, or count of obj type
1671+
...
16721672
*/
1673+
ObMySQLDateType(52) {
1674+
/*
1675+
* Encode.
1676+
*/
1677+
@Override
1678+
public byte[] encode(Object obj) {
1679+
return Serialization.encodeVi32((int) ((Date) obj).getTime());
1680+
}
1681+
1682+
/*
1683+
* Decode.
1684+
*/
1685+
@Override
1686+
public Object decode(ByteBuf buf, ObCollationType type) {
1687+
return new Date(Serialization.decodeVi32(buf) * 1000L);
1688+
}
1689+
1690+
/*
1691+
* Get encoded size.
1692+
*/
1693+
@Override
1694+
public int getEncodedSize(Object obj) {
1695+
return Serialization.getNeedBytes((int) ((Date) obj).getTime());
1696+
}
1697+
1698+
/*
1699+
* Get default obj meta.
1700+
*/
1701+
@Override
1702+
public ObObjMeta getDefaultObjMeta() {
1703+
return new ObObjMeta(this, ObCollationLevel.CS_LEVEL_NUMERIC,
1704+
ObCollationType.CS_TYPE_BINARY, (byte) 10);
1705+
}
1706+
1707+
/*
1708+
* Parse to comparable.
1709+
*/
1710+
@Override
1711+
public Date parseToComparable(Object o, ObCollationType ct)
1712+
throws IllegalArgumentException,
1713+
FeatureNotSupportedException {
1714+
1715+
if (o instanceof Date) {
1716+
return (Date) o;
1717+
}
1718+
1719+
if (o instanceof String) {
1720+
return TimeUtils.strToDate((String) o);
1721+
}
1722+
1723+
if (o instanceof ObVString) {
1724+
return TimeUtils.strToDate(((ObVString) o).getStringVal());
1725+
}
1726+
1727+
if (o instanceof Long) {
1728+
return new Date((Long) o);
1729+
}
1730+
1731+
throw new IllegalArgumentException("ObMySQLDateType can not parseToComparable argument:" + o);
1732+
}
1733+
},
1734+
ObMySQLDateTimeType(53) {
1735+
/*
1736+
* Encode.
1737+
*/
1738+
@Override
1739+
public byte[] encode(Object obj) {
1740+
// Date do not have timezone, when we use getTime, system will recognize it as our system timezone and transform it into UTC Time, which will changed the time.
1741+
// We should add back the lose part.
1742+
long targetTs = ((Date) obj).getTime()
1743+
+ OffsetDateTime.now().getOffset().getTotalSeconds() * 1000L;
1744+
return Serialization.encodeVi64(targetTs * 1000L);
1745+
}
1746+
1747+
/*
1748+
* Decode.
1749+
*/
1750+
@Override
1751+
public Object decode(ByteBuf buf, ObCollationType type) {
1752+
return new Date(Serialization.decodeVi64(buf) / 1000L
1753+
- OffsetDateTime.now().getOffset().getTotalSeconds() * 1000L);
1754+
}
1755+
1756+
/*
1757+
* Get encoded size.
1758+
*/
1759+
@Override
1760+
public int getEncodedSize(Object obj) {
1761+
return Serialization.getNeedBytes(((Date) obj).getTime() * 1000L);
1762+
}
1763+
1764+
/*
1765+
* Get default obj meta.
1766+
*/
1767+
@Override
1768+
public ObObjMeta getDefaultObjMeta() {
1769+
// scale set into 6 means microSecond
1770+
return new ObObjMeta(this, ObCollationLevel.CS_LEVEL_NUMERIC,
1771+
ObCollationType.CS_TYPE_BINARY, (byte) 6);
1772+
}
1773+
1774+
/*
1775+
* Parse to comparable.
1776+
*/
1777+
@Override
1778+
public Date parseToComparable(Object o, ObCollationType ct)
1779+
throws IllegalArgumentException,
1780+
FeatureNotSupportedException {
1781+
if (o instanceof String) {
1782+
return TimeUtils.strToDate((String) o);
1783+
}
1784+
return (Date) o;
1785+
}
1786+
};
1787+
/*
1788+
ObMaxType // invalid type, or count of obj type
1789+
*/
1790+
16731791
private int value;
16741792
private static Map<Integer, ObObjType> map = new HashMap<Integer, ObObjType>();
16751793

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package com.alipay.oceanbase.rpc;
2+
3+
import com.alipay.oceanbase.rpc.exception.ObTableException;
4+
import com.alipay.oceanbase.rpc.get.Get;
5+
import com.alipay.oceanbase.rpc.mutation.BatchOperation;
6+
import com.alipay.oceanbase.rpc.mutation.InsertOrUpdate;
7+
import com.alipay.oceanbase.rpc.mutation.Row;
8+
import com.alipay.oceanbase.rpc.mutation.result.BatchOperationResult;
9+
import com.alipay.oceanbase.rpc.stream.QueryResultSet;
10+
import com.alipay.oceanbase.rpc.util.ObTableClientTestUtil;
11+
import org.junit.Assert;
12+
import org.junit.Before;
13+
import org.junit.Test;
14+
15+
import java.text.SimpleDateFormat;
16+
import java.util.Date;
17+
import java.util.Map;
18+
19+
import static com.alipay.oceanbase.rpc.mutation.MutationFactory.colVal;
20+
import static com.alipay.oceanbase.rpc.mutation.MutationFactory.row;
21+
import static org.junit.Assert.assertThrows;
22+
import static org.junit.Assert.assertTrue;
23+
24+
/*
25+
CREATE TABLE IF NOT EXISTS `test_datetime_range` (
26+
`c1` bigint(20) NOT NULL,
27+
`c2` datetime(6) NOT NULL,
28+
`c3` varchar(20) DEFAULT NULL,
29+
KEY `idx_c2` (`c2`) LOCAL,
30+
PRIMARY KEY (`c1`, `c2`)
31+
) partition by range columns(c2) subpartition by key(c1) subpartition template (
32+
subpartition `p0`,
33+
subpartition `p1`,
34+
subpartition `p2`,
35+
subpartition `p3`)
36+
(partition `p0` values less than ('2023-12-01 00:00:00'),
37+
partition `p1` values less than ('2024-12-10 00:00:00'),
38+
partition `p2` values less than ('2025-12-20 00:00:00'),
39+
partition `p3` values less than ('2026-12-30 00:00:00'),
40+
partition `p4` values less than ('2027-01-01 00:00:00'),
41+
partition `p5` values less than MAXVALUE);
42+
*/
43+
public class ObTableDatetimeTest {
44+
ObTableClient client;
45+
public static String tableName = "test_datetime_range";
46+
47+
@Before
48+
public void setup() throws Exception {
49+
final ObTableClient obTableClient = ObTableClientTestUtil.newTestClient();
50+
obTableClient.init();
51+
this.client = obTableClient;
52+
}
53+
54+
@Test
55+
public void testSingle() throws Exception {
56+
String dateString = "2023-04-05 14:30:00";
57+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
58+
Date date = sdf.parse(dateString);
59+
try {
60+
Row rk = row(colVal("c1", 1L), colVal("c2", date), colVal("c3", 1L));
61+
client.insertOrUpdate(tableName).setRowKey(rk)
62+
.addMutateColVal(colVal("c4", "c4_val"))
63+
.execute();
64+
Map<String, Object> res = client.get(tableName)
65+
.setRowKey(rk)
66+
.select("c4")
67+
.execute();
68+
Assert.assertEquals("c4_val", res.get("c4"));
69+
70+
client.delete(tableName).setRowKey(rk).execute();
71+
} catch (Exception e) {
72+
System.out.println(e.getMessage());
73+
throw e;
74+
}
75+
}
76+
77+
@Test
78+
public void testBatch() throws Exception {
79+
String dateString1 = "2023-04-05 14:30:00";
80+
String dateString2 = "2024-04-05 14:30:00";
81+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
82+
Date date1 = sdf.parse(dateString1);
83+
Date date2 = sdf.parse(dateString2);
84+
try {
85+
Row rk1 = row(colVal("c1", 1L), colVal("c2", date1), colVal("c3", 1L));
86+
Row rk2 = row(colVal("c1", 1L), colVal("c2", date2), colVal("c3", 1L));
87+
BatchOperation batch = client.batchOperation(tableName);
88+
InsertOrUpdate insUp1 = client.insertOrUpdate(tableName).setRowKey(rk1)
89+
.addMutateColVal(colVal("c4", "c4_val"));
90+
InsertOrUpdate insUp2 = client.insertOrUpdate(tableName).setRowKey(rk2)
91+
.addMutateColVal(colVal("c4", "c4_val"));
92+
batch.addOperation(insUp1, insUp2);
93+
BatchOperationResult res = batch.execute();
94+
Assert.assertNotNull(res);
95+
Assert.assertNotEquals(0, res.get(0).getAffectedRows());
96+
Assert.assertNotEquals(0, res.get(1).getAffectedRows());
97+
98+
client.delete(tableName).setRowKey(rk1).execute();
99+
client.delete(tableName).setRowKey(rk2).execute();
100+
} catch (Exception e) {
101+
System.out.println(e.getMessage());
102+
throw e;
103+
}
104+
}
105+
106+
@Test
107+
public void testPkQuery() throws Exception {
108+
String dateString = "2023-04-05 14:30:00";
109+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
110+
Date date = sdf.parse(dateString);
111+
try {
112+
Row rk = row(colVal("c1", 1L), colVal("c2", date), colVal("c3", 1L));
113+
client.insertOrUpdate(tableName).setRowKey(rk)
114+
.addMutateColVal(colVal("c4", "c4_val"))
115+
.execute();
116+
117+
QueryResultSet res = client.query(tableName)
118+
.select("c4")
119+
.setScanRangeColumns("c1", "c2", "c3")
120+
.addScanRange(new Object[]{1L, date, 1L}, new Object[]{1L, date, 1L})
121+
.execute();
122+
Assert.assertTrue(res.next());
123+
Assert.assertEquals("c4_val", res.getRow().get("c4"));
124+
125+
client.delete(tableName).setRowKey(rk).execute();
126+
} catch (Exception e) {
127+
System.out.println(e.getMessage());
128+
throw e;
129+
}
130+
}
131+
132+
@Test
133+
public void testIndexQuery() throws Exception {
134+
String dateString = "2023-04-05 14:30:00";
135+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
136+
Date date = sdf.parse(dateString);
137+
try {
138+
Row rk = row(colVal("c1", 1L), colVal("c2", date), colVal("c3", 1L));
139+
client.insertOrUpdate(tableName).setRowKey(rk)
140+
.addMutateColVal(colVal("c4", "c4_val"))
141+
.execute();
142+
143+
QueryResultSet res = client.query(tableName)
144+
.indexName("idx_c2")
145+
.select("c4")
146+
.setScanRangeColumns("c1", "c2")
147+
.addScanRange(new Object[]{1L, date}, new Object[]{1L, date})
148+
.execute();
149+
Assert.assertTrue(res.next());
150+
Assert.assertEquals("c4_val", res.getRow().get("c4"));
151+
152+
client.delete(tableName).setRowKey(rk).execute();
153+
} catch (Exception e) {
154+
System.out.println(e.getMessage());
155+
throw e;
156+
}
157+
}
158+
}

src/test/resources/ci.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,4 +634,23 @@ CREATE TABLE IF NOT EXISTS `test_get` (
634634
PRIMARY KEY (`c1`, `c2`)
635635
) PARTITION BY KEY(`c1`) PARTITIONS 3;
636636

637+
CREATE TABLE IF NOT EXISTS `test_datetime_range` (
638+
`c1` bigint(20) NOT NULL,
639+
`c2` datetime(6) NOT NULL,
640+
`c3` bigint(20) NOT NULL,
641+
`c4` varchar(20) DEFAULT NULL,
642+
KEY `idx_c2` (`c1`, `c2`) LOCAL,
643+
PRIMARY KEY (`c1`, `c2`, `c3`)
644+
) partition by range columns(c2) subpartition by key(c1) subpartition template (
645+
subpartition `p0`,
646+
subpartition `p1`,
647+
subpartition `p2`,
648+
subpartition `p3`)
649+
(partition `p0` values less than ('2023-12-01 00:00:00'),
650+
partition `p1` values less than ('2024-12-10 00:00:00'),
651+
partition `p2` values less than ('2025-12-20 00:00:00'),
652+
partition `p3` values less than ('2026-12-30 00:00:00'),
653+
partition `p4` values less than ('2027-01-01 00:00:00'),
654+
partition `p5` values less than MAXVALUE);
655+
637656
alter system set kv_hotkey_throttle_threshold = 50;

0 commit comments

Comments
 (0)