Skip to content

Commit 6f9036e

Browse files
committed
Support default column values in Memory connector
1 parent 0dffa67 commit 6f9036e

File tree

5 files changed

+249
-10
lines changed

5 files changed

+249
-10
lines changed

plugin/trino-memory/src/main/java/io/trino/plugin/memory/ColumnInfo.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
import static com.google.common.base.MoreObjects.toStringHelper;
2222
import static java.util.Objects.requireNonNull;
2323

24-
public record ColumnInfo(MemoryColumnHandle handle, boolean nullable, Optional<String> comment)
24+
public record ColumnInfo(MemoryColumnHandle handle, Optional<String> defaultValue, boolean nullable, Optional<String> comment)
2525
{
2626
public ColumnInfo
2727
{
2828
requireNonNull(handle, "handle is null");
29+
requireNonNull(defaultValue, "defaultValue is null");
2930
requireNonNull(comment, "comment is null");
3031
}
3132

@@ -35,6 +36,7 @@ public ColumnMetadata getMetadata()
3536
return ColumnMetadata.builder()
3637
.setName(handle.name())
3738
.setType(handle.type())
39+
.setDefaultValue(defaultValue)
3840
.setNullable(nullable)
3941
.setComment(comment)
4042
.build();
@@ -46,6 +48,7 @@ public String toString()
4648
return toStringHelper(this)
4749
.add("name", handle.name())
4850
.add("type", handle.type())
51+
.add("defaultValue", defaultValue)
4952
.add("nullable", nullable)
5053
.add("comment", comment)
5154
.toString();

plugin/trino-memory/src/main/java/io/trino/plugin/memory/MemoryConnector.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.Set;
2929

3030
import static com.google.common.collect.Sets.immutableEnumSet;
31+
import static io.trino.spi.connector.ConnectorCapabilities.DEFAULT_COLUMN_VALUE;
3132
import static io.trino.spi.connector.ConnectorCapabilities.NOT_NULL_COLUMN_CONSTRAINT;
3233
import static java.util.Objects.requireNonNull;
3334

@@ -88,7 +89,7 @@ public ConnectorPageSinkProvider getPageSinkProvider()
8889
@Override
8990
public Set<ConnectorCapabilities> getCapabilities()
9091
{
91-
return immutableEnumSet(NOT_NULL_COLUMN_CONSTRAINT);
92+
return immutableEnumSet(DEFAULT_COLUMN_VALUE, NOT_NULL_COLUMN_CONSTRAINT);
9293
}
9394

9495
@Override

plugin/trino-memory/src/main/java/io/trino/plugin/memory/MemoryMetadata.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ public synchronized MemoryOutputTableHandle beginCreateTable(ConnectorSession se
348348
for (int i = 0; i < tableMetadata.getColumns().size(); i++) {
349349
ColumnMetadata column = tableMetadata.getColumns().get(i);
350350
MemoryColumnHandle handle = new MemoryColumnHandle(i, column.getName(), column.getType());
351-
columns.add(new ColumnInfo(handle, column.isNullable(), Optional.ofNullable(column.getComment())));
351+
columns.add(new ColumnInfo(handle, column.getDefaultValue(), column.isNullable(), Optional.ofNullable(column.getComment())));
352352
}
353353

354354
tableIds.put(tableMetadata.getTable(), tableId);
@@ -450,7 +450,7 @@ public synchronized void addColumn(ConnectorSession session, ConnectorTableHandl
450450

451451
List<ColumnInfo> columns = ImmutableList.<ColumnInfo>builderWithExpectedSize(table.columns().size() + 1)
452452
.addAll(table.columns())
453-
.add(new ColumnInfo(newColumn, column.isNullable(), Optional.ofNullable(column.getComment())))
453+
.add(new ColumnInfo(newColumn, column.getDefaultValue(), column.isNullable(), Optional.ofNullable(column.getComment())))
454454
.build();
455455

456456
tables.put(tableId, new TableInfo(tableId, table.schemaName(), table.tableName(), columns, table.truncated(), table.dataFragments(), table.comment()));
@@ -468,7 +468,7 @@ public synchronized void renameColumn(ConnectorSession session, ConnectorTableHa
468468

469469
List<ColumnInfo> columns = new ArrayList<>(table.columns());
470470
ColumnInfo columnInfo = columns.get(column.columnIndex());
471-
columns.set(column.columnIndex(), new ColumnInfo(newColumn, columnInfo.nullable(), columnInfo.comment()));
471+
columns.set(column.columnIndex(), new ColumnInfo(newColumn, columnInfo.defaultValue(), columnInfo.nullable(), columnInfo.comment()));
472472

473473
tables.put(tableId, new TableInfo(tableId, table.schemaName(), table.tableName(), ImmutableList.copyOf(columns), table.truncated(), table.dataFragments(), table.comment()));
474474
}
@@ -483,7 +483,7 @@ public synchronized void dropNotNullConstraint(ConnectorSession session, Connect
483483

484484
List<ColumnInfo> columns = new ArrayList<>(table.columns());
485485
ColumnInfo columnInfo = columns.get(column.columnIndex());
486-
columns.set(column.columnIndex(), new ColumnInfo(columnInfo.handle(), true, columnInfo.comment()));
486+
columns.set(column.columnIndex(), new ColumnInfo(columnInfo.handle(), columnInfo.defaultValue(), true, columnInfo.comment()));
487487

488488
tables.put(tableId, new TableInfo(tableId, table.schemaName(), table.tableName(), ImmutableList.copyOf(columns), table.truncated(), table.dataFragments(), table.comment()));
489489
}
@@ -669,7 +669,7 @@ public synchronized void setColumnComment(ConnectorSession session, ConnectorTab
669669
checkArgument(info != null, "Table not found");
670670
List<ColumnInfo> newColumns = info.columns().stream()
671671
.map(column -> column.handle().equals(columnHandle)
672-
? new ColumnInfo(column.handle(), column.nullable(), comment)
672+
? new ColumnInfo(column.handle(), column.defaultValue(), column.nullable(), comment)
673673
: column)
674674
.collect(toImmutableList());
675675
tables.put(table.id(), new TableInfo(table.id(), info.schemaName(), info.tableName(), newColumns, info.truncated(), info.dataFragments(), info.comment()));

plugin/trino-memory/src/test/java/io/trino/plugin/memory/TestMemoryConnectorTest.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import static io.trino.sql.planner.OptimizerConfig.JoinDistributionType.BROADCAST;
4242
import static org.assertj.core.api.Assertions.assertThat;
4343
import static org.assertj.core.api.Assertions.assertThatThrownBy;
44-
import static org.junit.jupiter.api.Assumptions.abort;
4544

4645
public class TestMemoryConnectorTest
4746
extends BaseConnectorTest
@@ -92,7 +91,6 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
9291
SUPPORTS_ADD_FIELD,
9392
SUPPORTS_AGGREGATION_PUSHDOWN,
9493
SUPPORTS_CREATE_MATERIALIZED_VIEW,
95-
SUPPORTS_DEFAULT_COLUMN_VALUE,
9694
SUPPORTS_DELETE,
9795
SUPPORTS_DEREFERENCE_PUSHDOWN,
9896
SUPPORTS_DROP_COLUMN,
@@ -111,7 +109,15 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior)
111109
@Override
112110
protected TestTable createTableWithDefaultColumns()
113111
{
114-
return abort("Memory connector does not support column default values");
112+
return newTrinoTable(
113+
"test_default_columns",
114+
"""
115+
(col_required BIGINT NOT NULL,
116+
col_nullable BIGINT,
117+
col_default BIGINT DEFAULT 43,
118+
col_nonnull_default BIGINT DEFAULT 42 NOT NULL,
119+
col_required2 BIGINT NOT NULL)
120+
""");
115121
}
116122

117123
@Test
Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package io.trino.plugin.memory;
15+
16+
import io.trino.testing.AbstractTestQueryFramework;
17+
import io.trino.testing.QueryRunner;
18+
import io.trino.testing.sql.TestTable;
19+
import org.intellij.lang.annotations.Language;
20+
import org.junit.jupiter.api.Test;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
24+
public class TestMemoryDefaultColumnValue
25+
extends AbstractTestQueryFramework
26+
{
27+
@Override
28+
protected QueryRunner createQueryRunner()
29+
throws Exception
30+
{
31+
return MemoryQueryRunner.builder().build();
32+
}
33+
34+
@Test
35+
void testNull()
36+
{
37+
assertDefaultValue("BOOLEAN", "null", null);
38+
}
39+
40+
@Test
41+
void testBoolean()
42+
{
43+
assertDefaultValue("BOOLEAN", "true", "true");
44+
assertDefaultValue("BOOLEAN", "false", "false");
45+
}
46+
47+
@Test
48+
void testTinyint()
49+
{
50+
assertDefaultValue("TINYINT", "-128", "TINYINT '-128'");
51+
assertDefaultValue("TINYINT", "127", "TINYINT '127'");
52+
}
53+
54+
@Test
55+
void testSmallint()
56+
{
57+
assertDefaultValue("SMALLINT", "-32768", "SMALLINT '-32768'");
58+
assertDefaultValue("SMALLINT", "32767", "SMALLINT '32767'");
59+
}
60+
61+
@Test
62+
void testInteger()
63+
{
64+
assertDefaultValue("INTEGER", "-2147483648", "-2147483648");
65+
assertDefaultValue("INTEGER", "2147483647", "2147483647");
66+
}
67+
68+
@Test
69+
void testBigint()
70+
{
71+
assertDefaultValue("BIGINT", "-9223372036854775808", "-9223372036854775808");
72+
assertDefaultValue("BIGINT", "9223372036854775807", "9223372036854775807");
73+
}
74+
75+
@Test
76+
void testReal()
77+
{
78+
assertDefaultValue("REAL", "REAL '3.14'");
79+
assertDefaultValue("REAL", "REAL '10.3e0'");
80+
assertDefaultValue("REAL", "123", "REAL '123'");
81+
82+
assertDefaultValue("REAL", "REAL 'NaN'");
83+
assertDefaultValue("REAL", "REAL '+Infinity'");
84+
assertDefaultValue("REAL", "REAL '-Infinity'");
85+
}
86+
87+
@Test
88+
void testDouble()
89+
{
90+
assertDefaultValue("DOUBLE", "3.14", "3.14E0");
91+
assertDefaultValue("DOUBLE", "1.0E100", "1.0E100");
92+
assertDefaultValue("DOUBLE", "1.23456E12", "1.23456E12");
93+
assertDefaultValue("DOUBLE", "123", "1.23E2");
94+
95+
assertDefaultValue("DOUBLE", "DOUBLE 'NaN'");
96+
assertDefaultValue("DOUBLE", "DOUBLE '+Infinity'");
97+
assertDefaultValue("DOUBLE", "DOUBLE '-Infinity'");
98+
}
99+
100+
@Test
101+
void testDecimal()
102+
{
103+
assertDefaultValue("DECIMAL(3)", "193", "DECIMAL '193'");
104+
assertDefaultValue("DECIMAL(3)", "-193", "DECIMAL '-193'");
105+
assertDefaultValue("DECIMAL(3, 1)", "10.0", "DECIMAL '10.0'");
106+
assertDefaultValue("DECIMAL(3, 1)", "-10.1", "DECIMAL '-10.1'");
107+
assertDefaultValue("DECIMAL(30, 5)", "3141592653589793238462643.38327", "DECIMAL '3141592653589793238462643.38327'");
108+
assertDefaultValue("DECIMAL(30, 5)", "-3141592653589793238462643.38327", "DECIMAL '-3141592653589793238462643.38327'");
109+
assertDefaultValue("DECIMAL(38)", "DECIMAL '27182818284590452353602874713526624977'");
110+
assertDefaultValue("DECIMAL(38)", "DECIMAL '-27182818284590452353602874713526624977'");
111+
}
112+
113+
@Test
114+
void testChar()
115+
{
116+
assertDefaultValue("CHAR(4)", "'test'", "'test'");
117+
assertDefaultValue("CHAR(10)", "'test'", "'test '");
118+
assertDefaultValue("CHAR(5)", "'攻殻機動隊'", "'攻殻機動隊'");
119+
assertDefaultValue("CHAR(1)", "'😂'", "'😂'");
120+
121+
// Trim trailing spaces
122+
assertDefaultValue("CHAR(4)", "'test '", "'test'");
123+
}
124+
125+
@Test
126+
void testVarchar()
127+
{
128+
assertDefaultValue("VARCHAR(4)", "'test'", "'test'");
129+
assertDefaultValue("VARCHAR(10)", "'test'", "'test'");
130+
assertDefaultValue("VARCHAR", "'test'", "'test'");
131+
assertDefaultValue("VARCHAR(5)", "'攻殻機動隊'", "'攻殻機動隊'");
132+
assertDefaultValue("VARCHAR(1)", "'😂'", "'😂'");
133+
134+
// Trim trailing spaces
135+
assertDefaultValue("VARCHAR(4)", "'test '", "'test'");
136+
}
137+
138+
@Test
139+
void testTime()
140+
{
141+
assertDefaultValue("TIME(0)", "TIME '00:00:01'");
142+
143+
assertDefaultValue("TIME(0)", "TIME '00:00:00'");
144+
assertDefaultValue("TIME(1)", "TIME '00:00:00.1'");
145+
assertDefaultValue("TIME(2)", "TIME '00:00:00.12'");
146+
assertDefaultValue("TIME(3)", "TIME '00:00:00.123'");
147+
assertDefaultValue("TIME(4)", "TIME '00:00:00.1234'");
148+
assertDefaultValue("TIME(5)", "TIME '00:00:00.12345'");
149+
assertDefaultValue("TIME(6)", "TIME '00:00:00.123456'");
150+
assertDefaultValue("TIME(7)", "TIME '00:00:00.1234567'");
151+
assertDefaultValue("TIME(8)", "TIME '00:00:00.12345678'");
152+
assertDefaultValue("TIME(9)", "TIME '00:00:00.123456789'");
153+
assertDefaultValue("TIME(10)", "TIME '00:00:00.1234567890'");
154+
assertDefaultValue("TIME(11)", "TIME '00:00:00.12345678901'");
155+
assertDefaultValue("TIME(12)", "TIME '00:00:00.123456789012'");
156+
}
157+
158+
@Test
159+
void testDate()
160+
{
161+
assertDefaultValue("DATE", "DATE '0001-01-01'", "DATE '0001-01-01'");
162+
assertDefaultValue("DATE", "DATE '1969-12-31'", "DATE '1969-12-31'");
163+
assertDefaultValue("DATE", "DATE '1970-01-01'", "DATE '1970-01-01'");
164+
assertDefaultValue("DATE", "DATE '9999-12-31'", "DATE '9999-12-31'");
165+
}
166+
167+
@Test
168+
void testTimestamp()
169+
{
170+
assertDefaultValue("TIMESTAMP(0)", "TIMESTAMP '1970-01-01 00:00:00'");
171+
assertDefaultValue("TIMESTAMP(1)", "TIMESTAMP '1970-01-01 00:00:00.9'");
172+
assertDefaultValue("TIMESTAMP(2)", "TIMESTAMP '1970-01-01 00:00:00.99'");
173+
assertDefaultValue("TIMESTAMP(3)", "TIMESTAMP '1970-01-01 00:00:00.999'");
174+
assertDefaultValue("TIMESTAMP(4)", "TIMESTAMP '1970-01-01 00:00:00.9999'");
175+
assertDefaultValue("TIMESTAMP(5)", "TIMESTAMP '1970-01-01 00:00:00.99999'");
176+
assertDefaultValue("TIMESTAMP(6)", "TIMESTAMP '1970-01-01 00:00:00.999999'");
177+
assertDefaultValue("TIMESTAMP(7)", "TIMESTAMP '1970-01-01 00:00:00.9999999'");
178+
assertDefaultValue("TIMESTAMP(8)", "TIMESTAMP '1970-01-01 00:00:00.99999999'");
179+
assertDefaultValue("TIMESTAMP(9)", "TIMESTAMP '1970-01-01 00:00:00.999999999'");
180+
assertDefaultValue("TIMESTAMP(10)", "TIMESTAMP '1970-01-01 00:00:00.9999999999'");
181+
assertDefaultValue("TIMESTAMP(11)", "TIMESTAMP '1970-01-01 00:00:00.99999999999'");
182+
assertDefaultValue("TIMESTAMP(12)", "TIMESTAMP '1970-01-01 00:00:00.999999999999'");
183+
184+
// Round fractional seconds
185+
assertDefaultValue("TIMESTAMP(0)", "TIMESTAMP '1970-01-01 00:00:00.4'", "TIMESTAMP '1970-01-01 00:00:00'");
186+
assertDefaultValue("TIMESTAMP(0)", "TIMESTAMP '1970-01-01 00:00:00.5'", "TIMESTAMP '1970-01-01 00:00:01'");
187+
assertDefaultValue("TIMESTAMP(9)", "TIMESTAMP '1970-01-01 00:00:00.9999999994'", "TIMESTAMP '1970-01-01 00:00:00.999999999'");
188+
assertDefaultValue("TIMESTAMP(9)", "TIMESTAMP '1970-01-01 00:00:00.9999999995'", "TIMESTAMP '1970-01-01 00:00:01.000000000'");
189+
}
190+
191+
@Test
192+
void testTimestampWithTimeZone()
193+
{
194+
assertDefaultValue("TIMESTAMP(0) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00 UTC'");
195+
assertDefaultValue("TIMESTAMP(1) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.9 UTC'");
196+
assertDefaultValue("TIMESTAMP(2) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.99 UTC'");
197+
assertDefaultValue("TIMESTAMP(3) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.999 UTC'");
198+
assertDefaultValue("TIMESTAMP(4) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.9999 UTC'");
199+
assertDefaultValue("TIMESTAMP(5) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.99999 UTC'");
200+
assertDefaultValue("TIMESTAMP(6) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.999999 UTC'");
201+
assertDefaultValue("TIMESTAMP(7) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.9999999 UTC'");
202+
assertDefaultValue("TIMESTAMP(8) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.99999999 UTC'");
203+
assertDefaultValue("TIMESTAMP(9) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.999999999 UTC'");
204+
assertDefaultValue("TIMESTAMP(10) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.9999999999 UTC'");
205+
assertDefaultValue("TIMESTAMP(11) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.99999999999 UTC'");
206+
assertDefaultValue("TIMESTAMP(12) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.999999999999 UTC'");
207+
208+
// Round fractional seconds
209+
assertDefaultValue("TIMESTAMP(0) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.4 UTC'", "TIMESTAMP '1970-01-01 00:00:00 UTC'");
210+
assertDefaultValue("TIMESTAMP(0) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.5 UTC'", "TIMESTAMP '1970-01-01 00:00:01 UTC'");
211+
assertDefaultValue("TIMESTAMP(9) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.9999999994 UTC'", "TIMESTAMP '1970-01-01 00:00:00.999999999 UTC'");
212+
assertDefaultValue("TIMESTAMP(9) WITH TIME ZONE", "TIMESTAMP '1970-01-01 00:00:00.9999999995 UTC'", "TIMESTAMP '1970-01-01 00:00:01.000000000 UTC'");
213+
}
214+
215+
private void assertDefaultValue(@Language("SQL") String columnType, @Language("SQL") String defaultValue)
216+
{
217+
assertDefaultValue(columnType, defaultValue, defaultValue);
218+
}
219+
220+
private void assertDefaultValue(@Language("SQL") String columnType, @Language("SQL") String literal, @Language("SQL") String expected)
221+
{
222+
try (TestTable table = newTrinoTable("test_default_value", "(id int, data " + columnType + " DEFAULT " + literal + ")")) {
223+
assertUpdate("INSERT INTO " + table.getName() + " (id) VALUES (1)", 1);
224+
assertThat(query("SELECT data FROM " + table.getName()))
225+
.skippingTypesCheck()
226+
.matches("VALUES " + expected);
227+
}
228+
}
229+
}

0 commit comments

Comments
 (0)