Skip to content

Commit a85138e

Browse files
Enable set_table_property procedure for Iceberg
1 parent 030e120 commit a85138e

File tree

4 files changed

+206
-1
lines changed

4 files changed

+206
-1
lines changed

presto-docs/src/main/sphinx/connector/iceberg.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,31 @@ Examples:
984984

985985
CALL iceberg.system.fast_forward('schema_name', 'table_name', 'branch1', 'main');
986986

987+
Set Table Property
988+
^^^^^^^^^^^^^^^^^^
989+
990+
Iceberg table property can be set from the catalog using the ``set_table_property`` procedure on the catalog's ``system`` schema.
991+
992+
The following arguments are available:
993+
994+
===================== ========== =============== =======================================================================
995+
Argument Name required type Description
996+
===================== ========== =============== =======================================================================
997+
``schema`` ✔️ string Schema of the table to update
998+
999+
``table_name`` ✔️ string Name of the table to update
1000+
1001+
``key`` ✔️ string Name of the table property
1002+
1003+
``value`` ✔️ string Value for the table property
1004+
===================== ========== =============== =======================================================================
1005+
1006+
Examples:
1007+
1008+
* Set table property ``commit.retry.num-retries`` to ``10`` for a Iceberg table ::
1009+
1010+
CALL iceberg.system.set_table_property('schema_name', 'table_name', 'commit.retry.num-retries', '10');
1011+
9871012
SQL Support
9881013
-----------
9891014

presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergCommonModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.facebook.presto.iceberg.procedure.RollbackToSnapshotProcedure;
4747
import com.facebook.presto.iceberg.procedure.RollbackToTimestampProcedure;
4848
import com.facebook.presto.iceberg.procedure.SetCurrentSnapshotProcedure;
49+
import com.facebook.presto.iceberg.procedure.SetTablePropertyProcedure;
4950
import com.facebook.presto.iceberg.procedure.UnregisterTableProcedure;
5051
import com.facebook.presto.iceberg.statistics.StatisticsFileCache;
5152
import com.facebook.presto.iceberg.statistics.StatisticsFileCacheKey;
@@ -165,6 +166,7 @@ public void setup(Binder binder)
165166
procedures.addBinding().toProvider(RemoveOrphanFiles.class).in(Scopes.SINGLETON);
166167
procedures.addBinding().toProvider(FastForwardBranchProcedure.class).in(Scopes.SINGLETON);
167168
procedures.addBinding().toProvider(SetCurrentSnapshotProcedure.class).in(Scopes.SINGLETON);
169+
procedures.addBinding().toProvider(SetTablePropertyProcedure.class).in(Scopes.SINGLETON);
168170

169171
// for orc
170172
binder.bind(EncryptionLibrary.class).annotatedWith(HiveDwrfEncryptionProvider.ForCryptoService.class).to(UnsupportedEncryptionLibrary.class).in(Scopes.SINGLETON);

presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/SetTablePropertyProcedure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public Procedure get()
7171
"set_table_property",
7272
ImmutableList.of(
7373
new Procedure.Argument("schema", VARCHAR),
74-
new Procedure.Argument("table", VARCHAR),
74+
new Procedure.Argument("table_name", VARCHAR),
7575
new Procedure.Argument("key", VARCHAR),
7676
new Procedure.Argument("value", VARCHAR)),
7777
SET_TABLE_PROPERTY.bindTo(this));
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
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 com.facebook.presto.iceberg.procedure;
15+
16+
import com.facebook.presto.iceberg.IcebergConfig;
17+
import com.facebook.presto.testing.QueryRunner;
18+
import com.facebook.presto.tests.AbstractTestQueryFramework;
19+
import com.google.common.collect.ImmutableMap;
20+
import org.apache.hadoop.conf.Configuration;
21+
import org.apache.iceberg.CatalogUtil;
22+
import org.apache.iceberg.Table;
23+
import org.apache.iceberg.catalog.Catalog;
24+
import org.apache.iceberg.catalog.TableIdentifier;
25+
import org.apache.iceberg.hadoop.HadoopCatalog;
26+
import org.testng.annotations.Test;
27+
28+
import java.io.File;
29+
import java.nio.file.Path;
30+
import java.util.Map;
31+
32+
import static com.facebook.presto.iceberg.CatalogType.HADOOP;
33+
import static com.facebook.presto.iceberg.IcebergQueryRunner.createIcebergQueryRunner;
34+
import static com.facebook.presto.iceberg.IcebergQueryRunner.getIcebergDataDirectoryPath;
35+
import static java.lang.String.format;
36+
import static org.testng.Assert.assertEquals;
37+
38+
public class TestSetTablePropertyProcedure
39+
extends AbstractTestQueryFramework
40+
{
41+
public static final String ICEBERG_CATALOG = "test_hadoop";
42+
public static final String TEST_SCHEMA = "tpch";
43+
44+
@Override
45+
protected QueryRunner createQueryRunner()
46+
throws Exception
47+
{
48+
return createIcebergQueryRunner(ImmutableMap.of(), HADOOP, ImmutableMap.of());
49+
}
50+
51+
public void createTable(String tableName)
52+
{
53+
assertUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (id integer, value VARCHAR)");
54+
}
55+
56+
public void dropTable(String tableName)
57+
{
58+
assertQuerySucceeds("DROP TABLE IF EXISTS " + TEST_SCHEMA + "." + tableName);
59+
}
60+
61+
@Test
62+
public void testSetTablePropertyProcedurePositionalArgs()
63+
{
64+
String tableName = "table_property_table_test";
65+
createTable(tableName);
66+
try {
67+
String propertyKey = "read.split.target-size";
68+
String propertyValue = "268435456";
69+
assertUpdate("INSERT INTO " + tableName + " VALUES (1, 'a')", 1);
70+
71+
Table table = loadTable(tableName);
72+
table.refresh();
73+
74+
assertEquals(table.properties().size(), 7);
75+
assertEquals(table.properties().get(propertyKey), null);
76+
77+
assertUpdate(format("CALL system.set_table_property('%s', '%s', '%s', '%s')", TEST_SCHEMA, tableName, propertyKey, propertyValue));
78+
table.refresh();
79+
80+
// now the table property read.split.target-size should have new value
81+
assertEquals(table.properties().size(), 8);
82+
assertEquals(table.properties().get(propertyKey), propertyValue);
83+
}
84+
finally {
85+
dropTable(tableName);
86+
}
87+
}
88+
89+
@Test
90+
public void testSetTablePropertyProcedureNamedArgs()
91+
{
92+
String tableName = "table_property_table_arg_test";
93+
createTable(tableName);
94+
try {
95+
String propertyKey = "read.split.target-size";
96+
String propertyValue = "268435456";
97+
assertUpdate("INSERT INTO " + tableName + " VALUES (1, 'a')", 1);
98+
99+
Table table = loadTable(tableName);
100+
table.refresh();
101+
102+
assertEquals(table.properties().size(), 7);
103+
assertEquals(table.properties().get(propertyKey), null);
104+
105+
assertUpdate(format("CALL system.set_table_property(schema => '%s', key => '%s', value => '%s', table_name => '%s')",
106+
TEST_SCHEMA, propertyKey, propertyValue, tableName));
107+
table.refresh();
108+
109+
// now the table property read.split.target-size should have new value
110+
assertEquals(table.properties().size(), 8);
111+
assertEquals(table.properties().get(propertyKey), propertyValue);
112+
}
113+
finally {
114+
dropTable(tableName);
115+
}
116+
}
117+
118+
@Test
119+
public void testSetTablePropertyProcedureUpdateExisting()
120+
{
121+
String tableName = "table_property_table_test_update";
122+
createTable(tableName);
123+
try {
124+
String propertyKey = "commit.retry.num-retries";
125+
String propertyValue = "10";
126+
127+
assertUpdate("INSERT INTO " + tableName + " VALUES (1, 'a')", 1);
128+
129+
Table table = loadTable(tableName);
130+
table.refresh();
131+
132+
assertEquals(table.properties().size(), 7);
133+
assertEquals(table.properties().get(propertyKey), "4");
134+
135+
assertUpdate(format("CALL system.set_table_property('%s', '%s', '%s', '%s')", TEST_SCHEMA, tableName, propertyKey, propertyValue));
136+
table.refresh();
137+
138+
// now the table property commit.retry.num-retries should have new value
139+
assertEquals(table.properties().size(), 7);
140+
assertEquals(table.properties().get(propertyKey), propertyValue);
141+
}
142+
finally {
143+
dropTable(tableName);
144+
}
145+
}
146+
147+
@Test
148+
public void testInvalidSetTablePropertyProcedureCases()
149+
{
150+
assertQueryFails("CALL system.set_table_property('test_table', key => 'key', value => 'value')",
151+
"line 1:1: Named and positional arguments cannot be mixed");
152+
assertQueryFails("CALL custom.set_table_property('test_table', 'key', 'value')",
153+
"Procedure not registered: custom.set_table_property");
154+
assertQueryFails("CALL system.set_table_property('schema', 'tablename', 'key')",
155+
"line 1:1: Required procedure argument 'value' is missing");
156+
assertQueryFails("CALL system.set_table_property('', 'main', 'key')",
157+
"line 1:1: Required procedure argument 'value' is missing");
158+
}
159+
160+
private Table loadTable(String tableName)
161+
{
162+
Catalog catalog = CatalogUtil.loadCatalog(HadoopCatalog.class.getName(), ICEBERG_CATALOG, getProperties(), new Configuration());
163+
return catalog.loadTable(TableIdentifier.of(TEST_SCHEMA, tableName));
164+
}
165+
166+
private Map<String, String> getProperties()
167+
{
168+
File metastoreDir = getCatalogDirectory();
169+
return ImmutableMap.of("warehouse", metastoreDir.toString());
170+
}
171+
172+
private File getCatalogDirectory()
173+
{
174+
Path dataDirectory = getDistributedQueryRunner().getCoordinator().getDataDirectory();
175+
Path catalogDirectory = getIcebergDataDirectoryPath(dataDirectory, HADOOP.name(), new IcebergConfig().getFileFormat(), false);
176+
return catalogDirectory.toFile();
177+
}
178+
}

0 commit comments

Comments
 (0)