Repository: empire-db Updated Branches: refs/heads/master 1458724fa -> 98059be83
EMPIREDB-254 Added new exception "ContraintViolationException" and function DBTable.checkUniqueConstraints() Project: http://git-wip-us.apache.org/repos/asf/empire-db/repo Commit: http://git-wip-us.apache.org/repos/asf/empire-db/commit/98059be8 Tree: http://git-wip-us.apache.org/repos/asf/empire-db/tree/98059be8 Diff: http://git-wip-us.apache.org/repos/asf/empire-db/diff/98059be8 Branch: refs/heads/master Commit: 98059be83b998d5ec482e04a65600cb24ccdefbd Parents: 1458724 Author: Rainer Döbele <[email protected]> Authored: Tue Jun 6 16:52:52 2017 +0200 Committer: Rainer Döbele <[email protected]> Committed: Tue Jun 6 16:52:52 2017 +0200 ---------------------------------------------------------------------- .../java/org/apache/empire/db/DBDatabase.java | 11 ++-- .../java/org/apache/empire/db/DBRecord.java | 17 +++++- .../main/java/org/apache/empire/db/DBTable.java | 42 +++++++++++++++ .../ConstraintViolationException.java | 56 ++++++++++++++++++++ 4 files changed, 122 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/empire-db/blob/98059be8/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java ---------------------------------------------------------------------- diff --git a/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java b/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java index bd4a754..a75132c 100644 --- a/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java +++ b/empire-db/src/main/java/org/apache/empire/db/DBDatabase.java @@ -23,6 +23,7 @@ import java.lang.ref.WeakReference; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.SQLIntegrityConstraintViolationException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; @@ -34,6 +35,7 @@ import org.apache.empire.commons.Options; import org.apache.empire.commons.StringUtils; import org.apache.empire.data.DataType; import org.apache.empire.db.DBRelation.DBCascadeAction; +import org.apache.empire.db.exceptions.ConstraintViolationException; import org.apache.empire.db.exceptions.DatabaseNotOpenException; import org.apache.empire.db.exceptions.EmpireSQLException; import org.apache.empire.db.exceptions.QueryFailedException; @@ -1331,10 +1333,13 @@ public abstract class DBDatabase extends DBObject // Return number of affected records return affected; - } catch (SQLException sqle) - { // Error + } catch (SQLIntegrityConstraintViolationException sqle) { + // ConstraintViolation + throw new ConstraintViolationException(this, sqlCmd, sqle); + } catch (SQLException sqle) { + // Other error throw new StatementFailedException(this, sqlCmd, sqle); - } + } } public final int executeSQL(String sqlCmd, Object[] sqlParams, Connection conn) http://git-wip-us.apache.org/repos/asf/empire-db/blob/98059be8/empire-db/src/main/java/org/apache/empire/db/DBRecord.java ---------------------------------------------------------------------- diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java index 942f01e..ffaeb19 100644 --- a/empire-db/src/main/java/org/apache/empire/db/DBRecord.java +++ b/empire-db/src/main/java/org/apache/empire/db/DBRecord.java @@ -414,7 +414,7 @@ public class DBRecord extends DBRecordData implements Record, Cloneable return false; return modified[index]; } - + /** * Returns true if the field was modified. * @@ -427,6 +427,21 @@ public class DBRecord extends DBRecordData implements Record, Cloneable } /** + * Returns true if any of the given fields was modified. + * + * @return true if any of the given fields were modified or false otherwise + */ + public final boolean wasAnyModified(Column... columns) + { + for (Column c : columns) + { + if (wasModified(getFieldIndex(c))) + return true; + } + return false; + } + + /** * Sets the modified state of a column.<BR> * This will force the field to be updated in the database, if set to TRUE. * http://git-wip-us.apache.org/repos/asf/empire-db/blob/98059be8/empire-db/src/main/java/org/apache/empire/db/DBTable.java ---------------------------------------------------------------------- diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTable.java b/empire-db/src/main/java/org/apache/empire/db/DBTable.java index c9d0923..058c49c 100644 --- a/empire-db/src/main/java/org/apache/empire/db/DBTable.java +++ b/empire-db/src/main/java/org/apache/empire/db/DBTable.java @@ -422,6 +422,48 @@ public class DBTable extends DBRowSet implements Cloneable } /** + * Checks weather a unique constraint is violated when inserting or updating a record.<BR> + * <P> + * @param id the record's primary key + * @param conn a valid JDBC connection + */ + public DBIndex checkUniqueConstraints(DBRecord rec, Connection conn) + { + for (DBIndex idx : getIndexes()) + { + if (idx.getType()==DBIndex.PRIMARYKEY) + { // Only for new records + if (!rec.isNew()) + continue; // not new + } + else if (idx.getType()==DBIndex.UNIQUE) + { // check if any of the fields were actually changed + if (!rec.isNew() && !rec.wasAnyModified(idx.getColumns())) + continue; // not modified + } + else + { // No unique index + continue; + } + // Check index + DBCommand cmd = db.createCommand(); + cmd.select(count()); + for (DBColumn c : idx.getColumns()) + { + Object value = rec.getValue(c); + cmd.where(c.is(value)); + } + int count = db.querySingleInt(cmd, conn); + if (count>0) + { // Index is violated + return idx; + } + } + // no index violation detected + return null; + } + + /** * returns the default cascade action for deletes on this table. * This is used as the default for newly created relations on this table and does not affect existing relations. * @return the delete cascade action for new relations (DBRelation.DBCascadeAction.CASCADE_RECORDS) are enabled http://git-wip-us.apache.org/repos/asf/empire-db/blob/98059be8/empire-db/src/main/java/org/apache/empire/db/exceptions/ConstraintViolationException.java ---------------------------------------------------------------------- diff --git a/empire-db/src/main/java/org/apache/empire/db/exceptions/ConstraintViolationException.java b/empire-db/src/main/java/org/apache/empire/db/exceptions/ConstraintViolationException.java new file mode 100644 index 0000000..22693cc --- /dev/null +++ b/empire-db/src/main/java/org/apache/empire/db/exceptions/ConstraintViolationException.java @@ -0,0 +1,56 @@ +/* + * 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.empire.db.exceptions; + +import java.sql.SQLException; + +import org.apache.empire.commons.ErrorType; +import org.apache.empire.db.DBObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConstraintViolationException extends EmpireSQLException +{ + // Logger + private static final Logger log = LoggerFactory.getLogger(ConstraintViolationException.class); + + /** + * Comment for <code>serialVersionUID</code> + */ + private static final long serialVersionUID = 1L; + + public static final ErrorType errorType = new ErrorType("error.db.statementFailed", "Error executing statement {0}.\r\nNative error is: {1}"); + + public ConstraintViolationException(DBObject obj, String sqlCmd, SQLException cause) + { + super(ConstraintViolationException.errorType, new String[] { sqlCmd, messageFromSQLException(driverFromObject(obj), cause) }, 1, cause); + } + + /** + * log the error + */ + @Override + protected void log() + { + if ( log.isErrorEnabled() ) + log.error(getMessage()); + else + super.log(); + } +}
