diff --git a/presto-docs/src/main/sphinx/connector/iceberg.rst b/presto-docs/src/main/sphinx/connector/iceberg.rst index 3f8a215bf7110..e57c8695ab146 100644 --- a/presto-docs/src/main/sphinx/connector/iceberg.rst +++ b/presto-docs/src/main/sphinx/connector/iceberg.rst @@ -732,28 +732,49 @@ example uses the earliest snapshot ID: ``2423571386296047175`` Procedures ---------- -Use the CALL statement to perform data manipulation or administrative tasks. Procedures are available in the ``system`` schema of the catalog. +Use the :doc:`/sql/call` statement to perform data manipulation or administrative tasks. Procedures are available in the ``system`` schema of the catalog. Register Table ^^^^^^^^^^^^^^ Iceberg tables for which table data and metadata already exist in the file system can be registered with the catalog. Use the ``register_table`` -procedure on the catalog's ``system`` schema and supply the target schema, -desired table name, and the location of the table metadata:: +procedure on the catalog's ``system`` schema to register a table which +already exists but does not known by the catalog. + +The following arguments are available: + +===================== ========== =============== ======================================================================= +Argument Name required type Description +===================== ========== =============== ======================================================================= +``schema`` ✔️ string Schema of the table to register + +``table_name`` ✔️ string Name of the table to register + +``metadata_location`` ✔️ string The location of the table metadata which is to be registered + +``metadata_file`` string An optionally specified metadata file which is to be registered +===================== ========== =============== ======================================================================= + +Examples: + +* Register a table through supplying the target schema, desired table name, and the location of the table metadata:: CALL iceberg.system.register_table('schema_name', 'table_name', 'hdfs://localhost:9000/path/to/iceberg/table/metadata/dir') + CALL iceberg.system.register_table(table_name => 'table_name', schema => 'schema_name', metadata_location => 'hdfs://localhost:9000/path/to/iceberg/table/metadata/dir') + .. note:: If multiple metadata files of the same version exist at the specified location, the most recently modified one is used. -A metadata file can optionally be included as an argument to ``register_table`` -where a specific metadata file contains the targeted table state:: +* Register a table through additionally supplying a specific metadata file:: CALL iceberg.system.register_table('schema_name', 'table_name', 'hdfs://localhost:9000/path/to/iceberg/table/metadata/dir', '00000-35a08aed-f4b0-4010-95d2-9d73ef4be01c.metadata.json') + CALL iceberg.system.register_table(table_name => 'table_name', schema => 'schema_name', metadata_location => 'hdfs://localhost:9000/path/to/iceberg/table/metadata/dir', metadata_file => '00000-35a08aed-f4b0-4010-95d2-9d73ef4be01c.metadata.json') + .. note:: The Iceberg REST catalog may not support table register depending on the @@ -775,10 +796,24 @@ Unregister Table ^^^^^^^^^^^^^^^^ Iceberg tables can be unregistered from the catalog using the ``unregister_table`` -procedure on the catalog's ``system`` schema:: +procedure on the catalog's ``system`` schema. + +The following arguments are available: + +===================== ========== =============== =================================== +Argument Name required type Description +===================== ========== =============== =================================== +``schema`` ✔️ string Schema of the table to unregister + +``table_name`` ✔️ string Name of the table to unregister +===================== ========== =============== =================================== + +Examples:: CALL iceberg.system.unregister_table('schema_name', 'table_name') + CALL iceberg.system.unregister_table(table_name => 'table_name', schema => 'schema_name') + .. note:: Table data and metadata remain in the filesystem after a call to diff --git a/presto-docs/src/main/sphinx/sql/call.rst b/presto-docs/src/main/sphinx/sql/call.rst index 3685b90da9561..4d240b5007350 100644 --- a/presto-docs/src/main/sphinx/sql/call.rst +++ b/presto-docs/src/main/sphinx/sql/call.rst @@ -18,6 +18,22 @@ Procedures can be provided by connectors to perform data manipulation or administrative tasks. For example, the :doc:`/connector/system` defines a procedure for killing a running query. +CALL statement supports passing arguments by name or by position. Mixing position and named arguments is not supported. + +* Named arguments + +Procedure arguments all have a name. When passing arguments by name, arguments can be in any order +and any optional argument can be omitted:: + + CALL catalog_name.system.procedure_name(arg_name_2 => arg_2, arg_name_1 => arg_1); + +* Positional arguments + +When passing arguments by position, only the ending arguments may be omitted if they are optional. +Intermediate parameters cannot be omitted:: + + CALL catalog_name.system.procedure_name(arg_1, arg_2, ... arg_n); + Some connectors, such as the :doc:`/connector/postgresql`, are for systems that have their own stored procedures. These stored procedures are separate from the connector-defined procedures discussed here and thus are not diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/RegisterTableProcedure.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/RegisterTableProcedure.java index 8dbb02c3cfe1e..28fc304ce8fdc 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/RegisterTableProcedure.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/RegisterTableProcedure.java @@ -84,9 +84,9 @@ public Procedure get() "register_table", ImmutableList.of( new Procedure.Argument("schema", VARCHAR), - new Procedure.Argument("table", VARCHAR), - new Procedure.Argument("metadataLocation", VARCHAR), - new Procedure.Argument("metadataFile", VARCHAR, false, null)), + new Procedure.Argument("table_name", VARCHAR), + new Procedure.Argument("metadata_location", VARCHAR), + new Procedure.Argument("metadata_file", VARCHAR, false, null)), REGISTER_TABLE.bindTo(this)); } diff --git a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/UnregisterTableProcedure.java b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/UnregisterTableProcedure.java index aca53fed6bdba..898257e6b85b8 100644 --- a/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/UnregisterTableProcedure.java +++ b/presto-iceberg/src/main/java/com/facebook/presto/iceberg/procedure/UnregisterTableProcedure.java @@ -57,7 +57,7 @@ public Procedure get() "unregister_table", ImmutableList.of( new Procedure.Argument("schema", VARCHAR), - new Procedure.Argument("table", VARCHAR)), + new Procedure.Argument("table_name", VARCHAR)), UNREGISTER_TABLE.bindTo(this)); } diff --git a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedSmokeTestBase.java b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedSmokeTestBase.java index 586ddb4438a43..513ba7f8ebecb 100644 --- a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedSmokeTestBase.java +++ b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/IcebergDistributedSmokeTestBase.java @@ -42,7 +42,7 @@ import static com.facebook.presto.iceberg.IcebergQueryRunner.getIcebergDataDirectoryPath; import static com.facebook.presto.iceberg.IcebergUtil.MIN_FORMAT_VERSION_FOR_DELETE; import static com.facebook.presto.iceberg.procedure.RegisterTableProcedure.METADATA_FOLDER_NAME; -import static com.facebook.presto.iceberg.procedure.TestIcebergRegisterProcedure.getMetadataFileLocation; +import static com.facebook.presto.iceberg.procedure.TestIcebergRegisterAndUnregisterProcedure.getMetadataFileLocation; import static com.facebook.presto.testing.MaterializedResult.resultBuilder; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Iterables.getOnlyElement; diff --git a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/procedure/TestIcebergRegisterProcedure.java b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/procedure/TestIcebergRegisterAndUnregisterProcedure.java similarity index 93% rename from presto-iceberg/src/test/java/com/facebook/presto/iceberg/procedure/TestIcebergRegisterProcedure.java rename to presto-iceberg/src/test/java/com/facebook/presto/iceberg/procedure/TestIcebergRegisterAndUnregisterProcedure.java index 1bed04dfb45d6..a3f0c66fb0e83 100644 --- a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/procedure/TestIcebergRegisterProcedure.java +++ b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/procedure/TestIcebergRegisterAndUnregisterProcedure.java @@ -60,7 +60,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; -public class TestIcebergRegisterProcedure +public class TestIcebergRegisterAndUnregisterProcedure extends AbstractTestQueryFramework { private Session session; @@ -126,6 +126,33 @@ public void testRegisterWithMetadataLocation() dropTable(tableName); } + @Test + public void testRegisterWithNamedArguments() + { + String tableName = "metadata_loc_named_arguments"; + try { + assertUpdate("CREATE TABLE " + tableName + " (id integer, value integer)"); + assertUpdate("INSERT INTO " + tableName + " VALUES(1, 1)", 1); + + String metadataLocation = getMetadataLocation(TEST_SCHEMA, tableName); + List metadataLocations = Arrays.asList( + metadataLocation, // without trailing slash + format("%s/", metadataLocation), // with training slash + format("%s/metadata", metadataLocation), // with metadata folder specified + format("%s/metadata/", metadataLocation)); + + for (String validLocation : metadataLocations) { + dropTableFromMetastore(TEST_SCHEMA, tableName); + + assertUpdate("CALL system.register_table(metadata_location => '" + validLocation + "', table_name => '" + tableName + "', schema => '" + TEST_SCHEMA + "')"); + assertQuery("SELECT * FROM " + tableName, "VALUES (1, 1)"); + } + } + finally { + dropTable(tableName); + } + } + @Test public void testRegisterWithMetadataLocationShowCreate() { @@ -256,10 +283,10 @@ public void testRegisterWithInvalidParameters() @Language("RegExp") String errorMessage = "line 1:1: Required procedure argument 'schema' is missing"; assertQueryFails("CALL system.register_table()", errorMessage); - errorMessage = "line 1:1: Required procedure argument 'table' is missing"; + errorMessage = "line 1:1: Required procedure argument 'table_name' is missing"; assertQueryFails("CALL system.register_table('" + TEST_SCHEMA + "')", errorMessage); - errorMessage = "line 1:1: Required procedure argument 'metadataLocation' is missing"; + errorMessage = "line 1:1: Required procedure argument 'metadata_location' is missing"; assertQueryFails("CALL system.register_table('" + TEST_SCHEMA + "', '" + TEST_TABLE_NAME + "')", errorMessage); errorMessage = "schemaName is empty"; @@ -373,6 +400,17 @@ public void testUnregisterTable() assertFalse(getQueryRunner().tableExists(getSession(), tableName)); } + @Test + public void testUnregisterTableWithNamedArguments() + { + String tableName = "unregister"; + assertUpdate("CREATE TABLE " + tableName + " (id integer, value integer)"); + + // Unregister table with procedure + assertUpdate("CALL system.unregister_table(table_name => '" + tableName + "', schema => '" + TEST_SCHEMA + "')"); + assertFalse(getQueryRunner().tableExists(getSession(), tableName)); + } + @Test public void testRegisterAndUnregisterTable() { @@ -426,7 +464,7 @@ public void testUnregisterWithInvalidParameters() @Language("RegExp") String errorMessage = "line 1:1: Required procedure argument 'schema' is missing"; assertQueryFails("CALL system.register_table()", errorMessage); - errorMessage = "line 1:1: Required procedure argument 'table' is missing"; + errorMessage = "line 1:1: Required procedure argument 'table_name' is missing"; assertQueryFails("CALL system.unregister_table('" + TEST_SCHEMA + "')", errorMessage); errorMessage = "schemaName is empty";