nssalian commented on a change in pull request #3275:
URL: https://github.com/apache/iceberg/pull/3275#discussion_r741603700



##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -250,10 +266,111 @@ public void setConf(Configuration conf) {
     this.conf = conf;
   }
 
+  private boolean insertProperties(Namespace namespace, Map<String, String> 
properties) {
+    String namespaceName = JdbcUtil.namespaceToString(namespace);
+
+    try {
+      int insertedRecords = connections.run(conn -> {
+        StringBuilder sqlStatement = new 
StringBuilder(JdbcUtil.INSERT_NAMESPACE_PROPERTIES_SQL);
+
+        for (int i = 0; i < properties.size() - 1; i++) {
+          sqlStatement.append(", " + JdbcUtil.INSERT_PROPERTIES_VALUES_BASE);

Review comment:
       Agreed. Will do.

##########
File path: core/src/test/java/org/apache/iceberg/jdbc/TestJdbcCatalog.java
##########
@@ -555,6 +556,66 @@ public void testDropNamespace() {
         "is not empty. 1 tables exist.", () -> 
catalog.dropNamespace(tbl4.namespace()));
   }
 
+  @Test
+  public void testCreateNamespace() {
+    Namespace testNamespace = Namespace.of("testDb", "ns1", "ns2");
+    // Test with null metadata
+    AssertHelpers.assertThrows("Cannot create a namespace with null or empty 
metadata", IllegalArgumentException.class,
+            () -> catalog.createNamespace(testNamespace, null));
+    Assert.assertFalse(catalog.namespaceExists(testNamespace));

Review comment:
       Addressing all the metadata emptiness questions: @rdblue  had a comment 
earlier about not allowing creation of namespaces without metadata. I think it 
makes sense to have this check since we are inserting metadata at the create 
and a record with metadata is indicative of a namespace existing.

##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -250,10 +266,111 @@ public void setConf(Configuration conf) {
     this.conf = conf;
   }
 
+  private boolean insertProperties(Namespace namespace, Map<String, String> 
properties) {
+    String namespaceName = JdbcUtil.namespaceToString(namespace);
+
+    try {
+      int insertedRecords = connections.run(conn -> {
+        StringBuilder sqlStatement = new 
StringBuilder(JdbcUtil.INSERT_NAMESPACE_PROPERTIES_SQL);
+
+        for (int i = 0; i < properties.size() - 1; i++) {

Review comment:
       It took me a bit of work to get the String parsing and the indexing 
right as well. I can clean it up with some of your JOINER suggestions.
   The checks are present to prevent this from being called with null or empty 
properties.

##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -116,6 +119,19 @@ private void initializeCatalogTables() throws 
InterruptedException, SQLException
       LOG.debug("Creating table {} to store iceberg catalog", 
JdbcUtil.CATALOG_TABLE_NAME);
       return conn.prepareStatement(JdbcUtil.CREATE_CATALOG_TABLE).execute();
     });
+
+    connections.run(conn -> {
+      DatabaseMetaData dbMeta = conn.getMetaData();
+      ResultSet tableExists = dbMeta.getTables(null, null, 
JdbcUtil.CREATE_NAMESPACE_PROPERTIES_TABLE, null);
+
+      if (tableExists.next()) {
+        return true;

Review comment:
       Yeah, I think the naming can't be be better. Tried to keep it simple and 
effective.
   
   Not sure I follow the `getTables` question. It's checking if there exists a 
row in the Tables table where this namespace exists. 
   ```
   protected static final String GET_NAMESPACE_SQL = "SELECT " + 
TABLE_NAMESPACE + " FROM " + CATALOG_TABLE_NAME +
         " WHERE " + CATALOG_NAME + " = ? AND " + TABLE_NAMESPACE + " LIKE ? 
LIMIT 1";
   ```
   not sure what you mean about the CREATE TABLE DDL being used? Could you 
clarify?

##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -116,6 +119,19 @@ private void initializeCatalogTables() throws 
InterruptedException, SQLException
       LOG.debug("Creating table {} to store iceberg catalog", 
JdbcUtil.CATALOG_TABLE_NAME);
       return conn.prepareStatement(JdbcUtil.CREATE_CATALOG_TABLE).execute();
     });
+
+    connections.run(conn -> {
+      DatabaseMetaData dbMeta = conn.getMetaData();
+      ResultSet tableExists = dbMeta.getTables(null, null, 
JdbcUtil.CREATE_NAMESPACE_PROPERTIES_TABLE, null);
+
+      if (tableExists.next()) {
+        return true;

Review comment:
       Oh, I think there's some confusion here. The right thing should be 
```NAMESPACE_PROPERTIES_TABLE_NAME``` instead of the create statement. I fixed 
it locally. I'll push it in the later commit.
   GET_NAMESPACE_SQL was right but for namespaceExists.

##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -250,10 +266,111 @@ public void setConf(Configuration conf) {
     this.conf = conf;
   }
 
+  private boolean insertProperties(Namespace namespace, Map<String, String> 
properties) {
+    String namespaceName = JdbcUtil.namespaceToString(namespace);
+
+    try {
+      int insertedRecords = connections.run(conn -> {
+        StringBuilder sqlStatement = new 
StringBuilder(JdbcUtil.INSERT_NAMESPACE_PROPERTIES_SQL);
+
+        for (int i = 0; i < properties.size() - 1; i++) {

Review comment:
       I see that. But I doubt there's much advantage to adding a separate 
string collection and then joining to the main string than doing it with string 
builder directly. 

##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -250,10 +266,111 @@ public void setConf(Configuration conf) {
     this.conf = conf;
   }
 
+  private boolean insertProperties(Namespace namespace, Map<String, String> 
properties) {
+    String namespaceName = JdbcUtil.namespaceToString(namespace);
+
+    try {
+      int insertedRecords = connections.run(conn -> {
+        StringBuilder sqlStatement = new 
StringBuilder(JdbcUtil.INSERT_NAMESPACE_PROPERTIES_SQL);
+
+        for (int i = 0; i < properties.size() - 1; i++) {
+          sqlStatement.append(", " + JdbcUtil.INSERT_PROPERTIES_VALUES_BASE);
+        }
+
+        try (PreparedStatement sql = 
conn.prepareStatement(sqlStatement.toString())) {
+          int rowIndex = 0;
+          for (Map.Entry<String, String> keyValue : properties.entrySet()) {
+            sql.setString(rowIndex + 1, catalogName);
+            sql.setString(rowIndex + 2, namespaceName);
+            sql.setString(rowIndex + 3, keyValue.getKey());
+            sql.setString(rowIndex + 4, keyValue.getValue());
+            rowIndex += 4;
+          }
+          return sql.executeUpdate();
+        }
+      });
+
+      if (insertedRecords == properties.size()) {
+        LOG.debug("Successfully committed to new namespace: {}", 
namespaceName);
+        return true;
+      } else {
+        throw new CommitFailedException("Failed to insertProperties to 
namespace %s in catalog %s", namespaceName,
+                catalogName);
+      }
+    } catch (InterruptedException e) {
+      Thread.currentThread().interrupt();
+      throw new UncheckedInterruptedException(e,
+              "Interrupted in call to insertProperties(namespace, properties) 
Namespace: %s", namespace);

Review comment:
       connections.run does throw this exception.

##########
File path: core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java
##########
@@ -250,10 +266,111 @@ public void setConf(Configuration conf) {
     this.conf = conf;
   }
 
+  private boolean insertProperties(Namespace namespace, Map<String, String> 
properties) {
+    String namespaceName = JdbcUtil.namespaceToString(namespace);
+
+    try {
+      int insertedRecords = connections.run(conn -> {
+        StringBuilder sqlStatement = new 
StringBuilder(JdbcUtil.INSERT_NAMESPACE_PROPERTIES_SQL);
+
+        for (int i = 0; i < properties.size() - 1; i++) {

Review comment:
       This makes sense. I like the idea of fixing the loop to make it all 
values in one go.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to