/*
*
* Copyright (c) 2013 - 2017 Lijun Liao
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
*
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* THE AUTHOR LIJUN LIAO. LIJUN LIAO DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the XiPKI software without
* disclosing the source code of your own applications.
*
* For more information, please contact Lijun Liao at this
* address: lijun.liao@gmail.com
*/
package org.xipki.commons.datasource.internal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.xipki.commons.common.util.ParamUtil;
import org.xipki.commons.datasource.DatabaseType;
/**
* JDBC error codes for a particular database.
*
* @author Lijun Liao
* @since 2.0.0
*/
public class SqlErrorCodes {
// CHECKSTYLE:SKIP
private static class DB2 extends SqlErrorCodes {
DB2() {
super();
badSqlGrammarCodes = toSet(-7, -29, -97, -104, -109, -115, -128, -199, -204, -206, -301,
-408, -441, -491);
duplicateKeyCodes = toSet(-803);
dataIntegrityViolationCodes = toSet(-407, -530, -531, -532, -543, -544, -545, -603,
-667);
dataAccessResourceFailureCodes = toSet(-904, -971);
transientDataAccessResourceCodes = toSet(-1035, -1218, -30080, -30081);
deadlockLoserCodes = toSet(-911, -913);
}
} // class DB2
private static class H2 extends SqlErrorCodes {
H2() {
super();
badSqlGrammarCodes = toSet(42000, 42001, 42101, 42102, 42111, 42112, 42121, 42122,
42132);
duplicateKeyCodes = toSet(23001, 23505);
dataIntegrityViolationCodes = toSet(22001, 22003, 22012, 22018, 22025, 23000, 23002,
23003, 23502, 23503, 23506, 23507, 23513);
dataAccessResourceFailureCodes = toSet(90046, 90100, 90117, 90121, 90126);
cannotAcquireLockCodes = toSet(50200);
}
} // class H2
// CHECKSTYLE:SKIP
private static class HSQL extends SqlErrorCodes {
HSQL() {
super();
badSqlGrammarCodes = toSet(-22, -28);
duplicateKeyCodes = toSet(-104);
dataIntegrityViolationCodes = toSet(-9);
dataAccessResourceFailureCodes = toSet(-80);
}
} // class HSQL
// CHECKSTYLE:SKIP
private static class MySQL extends SqlErrorCodes {
MySQL() {
super();
badSqlGrammarCodes = toSet(1054, 1064, 1146);
duplicateKeyCodes = toSet(1062);
dataIntegrityViolationCodes = toSet(630, 839, 840, 893, 1169, 1215, 1216, 1217, 1364,
1451, 1452, 1557);
dataAccessResourceFailureCodes = toSet(1);
cannotAcquireLockCodes = toSet(1205);
deadlockLoserCodes = toSet(1213);
}
} // class MySQL
// CHECKSTYLE:SKIP
private static class MariaDB extends MySQL {
MariaDB() {
super();
}
} // class MariaDB
private static class Oracle extends SqlErrorCodes {
Oracle() {
super();
badSqlGrammarCodes = toSet(900, 903, 904, 917, 936, 942, 17006, 6550);
invalidResultSetAccessCodes = toSet(17003);
duplicateKeyCodes = toSet(1);
dataIntegrityViolationCodes = toSet(1400, 1722, 2291, 2292);
dataAccessResourceFailureCodes = toSet(17002, 17447);
cannotAcquireLockCodes = toSet(54, 30006);
cannotSerializeTransactionCodes = toSet(8177);
deadlockLoserCodes = toSet(60);
}
} // class Oracle
// CHECKSTYLE:SKIP
private static class PostgreSQL extends SqlErrorCodes {
PostgreSQL() {
super();
useSqlStateForTranslation = true;
badSqlGrammarCodes = toSet("03000", "42000", "42601", "42602", "42622", "42804",
"42P01");
duplicateKeyCodes = toSet(23505);
dataIntegrityViolationCodes = toSet(23000, 23502, 23503, 23514);
dataAccessResourceFailureCodes = toSet(53000, 53100, 53200, 53300);
cannotAcquireLockCodes = toSet("55P03");
cannotSerializeTransactionCodes = toSet(40001);
deadlockLoserCodes = toSet("40P01");
}
} // class PostgreSQL
protected boolean useSqlStateForTranslation;
protected Set<String> badSqlGrammarCodes;
protected Set<String> invalidResultSetAccessCodes;
protected Set<String> duplicateKeyCodes;
protected Set<String> dataIntegrityViolationCodes;
protected Set<String> permissionDeniedCodes;
protected Set<String> dataAccessResourceFailureCodes;
protected Set<String> transientDataAccessResourceCodes;
protected Set<String> cannotAcquireLockCodes;
protected Set<String> deadlockLoserCodes;
protected Set<String> cannotSerializeTransactionCodes;
private SqlErrorCodes() {
badSqlGrammarCodes = Collections.emptySet();
invalidResultSetAccessCodes = Collections.emptySet();
duplicateKeyCodes = Collections.emptySet();
dataIntegrityViolationCodes = Collections.emptySet();
permissionDeniedCodes = Collections.emptySet();
dataAccessResourceFailureCodes = Collections.emptySet();
transientDataAccessResourceCodes = Collections.emptySet();
cannotAcquireLockCodes = Collections.emptySet();
deadlockLoserCodes = Collections.emptySet();
cannotSerializeTransactionCodes = Collections.emptySet();
}
public boolean isUseSqlStateForTranslation() {
return useSqlStateForTranslation;
}
public Set<String> getBadSqlGrammarCodes() {
return badSqlGrammarCodes;
}
public Set<String> getInvalidResultSetAccessCodes() {
return invalidResultSetAccessCodes;
}
public Set<String> getDuplicateKeyCodes() {
return duplicateKeyCodes;
}
public Set<String> getDataIntegrityViolationCodes() {
return dataIntegrityViolationCodes;
}
public Set<String> getPermissionDeniedCodes() {
return permissionDeniedCodes;
}
public Set<String> getDataAccessResourceFailureCodes() {
return dataAccessResourceFailureCodes;
}
public Set<String> getTransientDataAccessResourceCodes() {
return transientDataAccessResourceCodes;
}
public Set<String> getCannotAcquireLockCodes() {
return cannotAcquireLockCodes;
}
public Set<String> getDeadlockLoserCodes() {
return deadlockLoserCodes;
}
public Set<String> getCannotSerializeTransactionCodes() {
return cannotSerializeTransactionCodes;
}
public static SqlErrorCodes newInstance(final DatabaseType dbType) {
ParamUtil.requireNonNull("dbType", dbType);
switch (dbType) {
case DB2:
return new DB2();
case H2:
return new H2();
case HSQL:
return new HSQL();
case MYSQL:
return new MySQL();
case MARIADB:
return new MariaDB();
case ORACLE:
return new Oracle();
case POSTGRES:
return new PostgreSQL();
case UNKNOWN:
return new SqlErrorCodes();
default:
throw new RuntimeException("should not reach here, unknown database type " + dbType);
}
}
private static Set<String> toSet(final String... strs) {
if (strs == null || strs.length == 0) {
return Collections.emptySet();
}
Set<String> set = new HashSet<String>();
for (String str : strs) {
set.add(str);
}
return Collections.unmodifiableSet(set);
}
private static Set<String> toSet(final int... ints) {
if (ints == null || ints.length == 0) {
return Collections.emptySet();
}
Set<String> set = new HashSet<String>();
for (int i : ints) {
set.add(Integer.toString(i));
}
return Collections.unmodifiableSet(set);
}
}