Copilot commented on code in PR #6552:
URL: https://github.com/apache/hive/pull/6552#discussion_r3444810195


##########
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/RawStore.java:
##########
@@ -1294,14 +1301,22 @@ Map<String, String> 
updateTableColumnStatistics(ColumnStatistics colStats, Strin
    * @throws InvalidInputException unable to record the stats for the table
    */
   @Deprecated
-  Map<String, String> updatePartitionColumnStatistics(ColumnStatistics 
statsObj,
+  default Map<String, String> updatePartitionColumnStatistics(ColumnStatistics 
statsObj,
       List<String> partVals, String validWriteIds, long writeId)
-      throws NoSuchObjectException, MetaException, InvalidObjectException, 
InvalidInputException;
+      throws NoSuchObjectException, MetaException, InvalidObjectException, 
InvalidInputException {
+    ColumnStatisticsDesc statsDesc = statsObj.getStatsDesc();
+    Table table = unwrap(TableStore.class)
+        .getTable(new TableName(statsDesc.getCatName(), statsDesc.getDbName(), 
statsDesc.getTableName()), null, -1);
+    MTable mTable = ensureGetMTable(statsDesc.getCatName(), 
statsDesc.getDbName(), statsDesc.getTableName());
+    return updatePartitionColumnStatistics(table, mTable, statsObj, partVals, 
validWriteIds, writeId);

Review Comment:
   The deprecated updatePartitionColumnStatistics(...) default implementation 
uses statsDesc.getCatName() directly. ColumnStatisticsDesc may not have catName 
set (older clients), which will pass null into TableName/ensureGetMTable and 
can trigger an NPE via normalizeIdentifier(catName) in 
TableStoreImpl.ensureGetMTable. Please default the catalog name before 
constructing TableName / calling ensureGetMTable.



##########
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/metastore/impl/WMStoreImpl.java:
##########
@@ -0,0 +1,1053 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hive.metastore.metastore.impl;
+
+import com.google.common.collect.Sets;
+
+import javax.jdo.Query;
+import java.sql.SQLIntegrityConstraintViolationException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.QueryWrapper;
+import org.apache.hadoop.hive.metastore.RawStore;
+import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
+import org.apache.hadoop.hive.metastore.api.InvalidObjectException;
+import org.apache.hadoop.hive.metastore.api.InvalidOperationException;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
+import org.apache.hadoop.hive.metastore.api.RuntimeStat;
+import org.apache.hadoop.hive.metastore.api.WMFullResourcePlan;
+import org.apache.hadoop.hive.metastore.api.WMMapping;
+import org.apache.hadoop.hive.metastore.api.WMNullablePool;
+import org.apache.hadoop.hive.metastore.api.WMNullableResourcePlan;
+import org.apache.hadoop.hive.metastore.api.WMPool;
+import org.apache.hadoop.hive.metastore.api.WMPoolTrigger;
+import org.apache.hadoop.hive.metastore.api.WMResourcePlan;
+import org.apache.hadoop.hive.metastore.api.WMResourcePlanStatus;
+import org.apache.hadoop.hive.metastore.api.WMTrigger;
+import org.apache.hadoop.hive.metastore.api.WMValidateResourcePlanResponse;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.apache.hadoop.hive.metastore.metastore.RawStoreAware;
+import org.apache.hadoop.hive.metastore.metastore.iface.WMStore;
+import org.apache.hadoop.hive.metastore.model.MRuntimeStat;
+import org.apache.hadoop.hive.metastore.model.MWMMapping;
+import org.apache.hadoop.hive.metastore.model.MWMPool;
+import org.apache.hadoop.hive.metastore.model.MWMResourcePlan;
+import org.apache.hadoop.hive.metastore.model.MWMTrigger;
+import org.apache.hadoop.hive.metastore.utils.MetaStoreUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static 
org.apache.hadoop.hive.metastore.utils.StringUtils.normalizeIdentifier;
+
+public class WMStoreImpl extends RawStoreAware implements WMStore {
+  private static final Logger LOG = LoggerFactory.getLogger(WMStoreImpl.class);
+  private static final DateTimeFormatter YMDHMS_FORMAT = 
DateTimeFormatter.ofPattern(
+      "yyyy_MM_dd_HH_mm_ss");
+
+  private void checkForConstraintException(Exception e, String msg) throws 
AlreadyExistsException {
+    if (getConstraintException(e) != null) {
+      LOG.error(msg, e);
+      throw new AlreadyExistsException(msg);
+    }
+  }
+
+  private Throwable getConstraintException(Throwable t) {
+    while (t != null) {
+      if (t instanceof SQLIntegrityConstraintViolationException) {
+        return t;
+      }
+      t = t.getCause();
+    }
+    return null;
+  }

Review Comment:
   getConstraintException only detects 
java.sql.SQLIntegrityConstraintViolationException. In practice (e.g., Derby) 
uniqueness/foreign-key violations are often wrapped as vendor SQLException 
types and won't be caught, which leaks verbose 
JDODataStoreException/MetaException to users and breaks the expected 
AlreadyExistsException / InvalidOperationException behavior (see updated 
q.out). Consider also checking SQLException SQLState class "23" (integrity 
constraint violation) when walking the cause chain.



##########
ql/src/test/results/clientpositive/llap/resourceplan.q.out:
##########
@@ -535,7 +535,12 @@ FAILED: SemanticException Invalid create arguments 
(tok_create_rp plan_3 (tok_qu
 PREHOOK: query: ALTER RESOURCE PLAN plan_1 RENAME TO plan_2
 PREHOOK: type: ALTER RESOURCEPLAN
 PREHOOK: Output: dummyHostnameForTest
-FAILED: Execution Error, return code 40000 from 
org.apache.hadoop.hive.ql.ddl.DDLTask. AlreadyExistsException(message:Resource 
plan name should be unique: )
+FAILED: Execution Error, return code 40000 from 
org.apache.hadoop.hive.ql.ddl.DDLTask. 
MetaException(message:JDODataStoreException: Update of object with id 
"1[OID]org.apache.hadoop.hive.metastore.model.MWMResourcePlan" using statement 
"UPDATE WM_RESOURCEPLAN SET "NAME"=? WHERE RP_ID=?" failed : 
org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException:
 The statement was aborted because it would have caused a duplicate key value 
in a unique or primary key constraint or unique index identified by 
'UNIQUE_WM_RESOURCEPLAN' defined on 'WM_RESOURCEPLAN'.
+#### A masked pattern was here ####
+Caused by: ERROR 23505: The statement was aborted because it would have caused 
a duplicate key value in a unique or primary key constraint or unique index 
identified by 'UNIQUE_WM_RESOURCEPLAN' defined on 'WM_RESOURCEPLAN'.
+#### A masked pattern was here ####
+
+Root cause: ERROR 23505: The statement was aborted because it would have 
caused a duplicate key value in a unique or primary key constraint or unique 
index identified by 'UNIQUE_WM_RESOURCEPLAN' defined on 'WM_RESOURCEPLAN'.)

Review Comment:
   This golden file update is now asserting a verbose 
MetaException/JDODataStoreException for a resource plan rename collision. That 
appears to be a regression in error mapping (previously a clean 
AlreadyExistsException); it would be better to fix WMStoreImpl to recognize 
integrity-constraint violations across DBs and keep the stable user-facing 
error, rather than baking DB-specific JDO exception text into test output.



##########
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/metastore/impl/ConstraintStoreImpl.java:
##########
@@ -0,0 +1,1294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hive.metastore.metastore.impl;
+
+import javax.jdo.Query;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.common.TableName;
+import org.apache.hadoop.hive.metastore.QueryWrapper;
+import org.apache.hadoop.hive.metastore.RawStore;
+import org.apache.hadoop.hive.metastore.api.AllTableConstraintsRequest;
+import org.apache.hadoop.hive.metastore.api.CheckConstraintsRequest;
+import org.apache.hadoop.hive.metastore.api.DefaultConstraintsRequest;
+import org.apache.hadoop.hive.metastore.api.ForeignKeysRequest;
+import org.apache.hadoop.hive.metastore.api.InvalidInputException;
+import org.apache.hadoop.hive.metastore.api.InvalidObjectException;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
+import org.apache.hadoop.hive.metastore.api.NotNullConstraintsRequest;
+import org.apache.hadoop.hive.metastore.api.PrimaryKeysRequest;
+import org.apache.hadoop.hive.metastore.api.SQLAllTableConstraints;
+import org.apache.hadoop.hive.metastore.api.SQLCheckConstraint;
+import org.apache.hadoop.hive.metastore.api.SQLDefaultConstraint;
+import org.apache.hadoop.hive.metastore.api.SQLForeignKey;
+import org.apache.hadoop.hive.metastore.api.SQLNotNullConstraint;
+import org.apache.hadoop.hive.metastore.api.SQLPrimaryKey;
+import org.apache.hadoop.hive.metastore.api.SQLUniqueConstraint;
+import org.apache.hadoop.hive.metastore.api.Table;
+import org.apache.hadoop.hive.metastore.api.UniqueConstraintsRequest;
+import org.apache.hadoop.hive.metastore.metastore.GetListHelper;
+import org.apache.hadoop.hive.metastore.metastore.RawStoreAware;
+import org.apache.hadoop.hive.metastore.metastore.iface.ConstraintStore;
+import org.apache.hadoop.hive.metastore.metastore.iface.TableStore;
+import org.apache.hadoop.hive.metastore.model.MColumnDescriptor;
+import org.apache.hadoop.hive.metastore.model.MConstraint;
+import org.apache.hadoop.hive.metastore.model.MFieldSchema;
+import org.apache.hadoop.hive.metastore.model.MTable;
+
+import static 
org.apache.hadoop.hive.metastore.utils.MetaStoreUtils.getDefaultCatalog;
+import static 
org.apache.hadoop.hive.metastore.utils.StringUtils.normalizeIdentifier;
+
+public class ConstraintStoreImpl extends RawStoreAware implements 
ConstraintStore {
+  private Configuration conf;
+
+  @Override
+  public SQLAllTableConstraints createTableWithConstraints(Table tbl, 
SQLAllTableConstraints constraints)
+      throws InvalidObjectException, MetaException {
+    baseStore.unwrap(TableStore.class).createTable(tbl);
+    // Add constraints.
+    // We need not do a deep retrieval of the Table Column Descriptor while 
persisting the
+    // constraints since this transaction involving create table is not yet 
committed.
+    if (CollectionUtils.isNotEmpty(constraints.getForeignKeys())) {
+      constraints.setForeignKeys(addForeignKeys(constraints.getForeignKeys(), 
false, constraints.getPrimaryKeys(),
+          constraints.getUniqueConstraints()));
+    }
+    if (CollectionUtils.isNotEmpty(constraints.getPrimaryKeys())) {
+      constraints.setPrimaryKeys(addPrimaryKeys(constraints.getPrimaryKeys(), 
false));
+    }
+    if (CollectionUtils.isNotEmpty(constraints.getUniqueConstraints())) {
+      
constraints.setUniqueConstraints(addUniqueConstraints(constraints.getUniqueConstraints(),
 false));
+    }
+    if (CollectionUtils.isNotEmpty(constraints.getNotNullConstraints())) {
+      
constraints.setNotNullConstraints(addNotNullConstraints(constraints.getNotNullConstraints(),
 false));
+    }
+    if (CollectionUtils.isNotEmpty(constraints.getDefaultConstraints())) {
+      
constraints.setDefaultConstraints(addDefaultConstraints(constraints.getDefaultConstraints(),
 false));
+    }
+    if (CollectionUtils.isNotEmpty(constraints.getCheckConstraints())) {
+      
constraints.setCheckConstraints(addCheckConstraints(constraints.getCheckConstraints(),
 false));
+    }
+    return constraints;
+  }
+
+  private List<MConstraint> listAllTableConstraintsWithOptionalConstraintName(
+      String catName, String dbName, String tableName, String constraintname) {
+    catName = normalizeIdentifier(catName);
+    dbName = normalizeIdentifier(dbName);
+    tableName = normalizeIdentifier(tableName);
+    constraintname = 
constraintname!=null?normalizeIdentifier(constraintname):null;
+    List<MConstraint> mConstraints = null;
+    List<String> constraintNames = new ArrayList<>();
+
+    try (QueryWrapper queryForConstraintName =
+             new QueryWrapper(pm.newQuery("select constraintName from 
org.apache.hadoop.hive.metastore.model.MConstraint  where "
+        + "((parentTable.tableName == ptblname && parentTable.database.name == 
pdbname && " +
+        "parentTable.database.catalogName == pcatname) || "
+        + "(childTable != null && childTable.tableName == ctblname &&" +
+        "childTable.database.name == cdbname && 
childTable.database.catalogName == ccatname)) " +
+        (constraintname != null ? " && constraintName == constraintname" : 
"")));
+         QueryWrapper queryForMConstraint = new 
QueryWrapper(pm.newQuery(MConstraint.class))) {
+
+      queryForConstraintName.declareParameters("java.lang.String ptblname, 
java.lang.String pdbname,"
+          + "java.lang.String pcatname, java.lang.String ctblname, 
java.lang.String cdbname," +
+          "java.lang.String ccatname" +
+          (constraintname != null ? ", java.lang.String constraintname" : ""));
+      Collection<?> constraintNamesColl =
+          constraintname != null ?
+              ((Collection<?>) queryForConstraintName.
+                  executeWithArray(tableName, dbName, catName, tableName, 
dbName, catName, constraintname)):
+              ((Collection<?>) queryForConstraintName.
+                  executeWithArray(tableName, dbName, catName, tableName, 
dbName, catName));
+      for (Iterator<?> i = constraintNamesColl.iterator(); i.hasNext();) {
+        String currName = (String) i.next();
+        constraintNames.add(currName);
+      }
+
+      queryForMConstraint.setFilter("param.contains(constraintName)");
+      queryForMConstraint.declareParameters("java.util.Collection param");
+      Collection<?> constraints = 
(Collection<?>)queryForMConstraint.execute(constraintNames);
+      mConstraints = new ArrayList<>();
+      for (Iterator<?> i = constraints.iterator(); i.hasNext();) {
+        MConstraint currConstraint = (MConstraint) i.next();
+        mConstraints.add(currConstraint);
+      }
+    }
+    return mConstraints;
+  }
+
+  private boolean constraintNameAlreadyExists(MTable table, String 
constraintName) {
+    Query<MConstraint> constraintExistsQuery = null;
+    constraintName = normalizeIdentifier(constraintName);
+    constraintExistsQuery = pm.newQuery(MConstraint.class,
+        "parentTable == parentTableP && constraintName == constraintNameP");
+    constraintExistsQuery.declareParameters("MTable parentTableP, 
java.lang.String constraintNameP");
+    constraintExistsQuery.setUnique(true);
+    constraintExistsQuery.setResult("constraintName");
+    String constraintNameIfExists = (String) 
constraintExistsQuery.executeWithArray(table, constraintName);
+    return constraintNameIfExists != null && !constraintNameIfExists.isEmpty();
+  }

Review Comment:
   constraintNameAlreadyExists creates a JDO Query but never closes it. Over 
time (and especially in loops like generateConstraintName) this can leak query 
resources. Prefer using QueryWrapper (try-with-resources) like the other query 
sites in this class.



-- 
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