You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IciqlException.java 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * Copyright 2011 James Moger.
  3. * Copyright 2012 Frédéric Gaillard
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.iciql;
  18. import java.sql.SQLException;
  19. import java.text.MessageFormat;
  20. import java.util.regex.Pattern;
  21. /**
  22. * Iciql wraps all exceptions with this class.
  23. */
  24. public class IciqlException extends RuntimeException {
  25. public static final int CODE_UNMAPPED_FIELD = 1;
  26. public static final int CODE_DUPLICATE_KEY = 2;
  27. public static final int CODE_OBJECT_NOT_FOUND = 3;
  28. public static final int CODE_OBJECT_ALREADY_EXISTS = 4;
  29. public static final int CODE_CONSTRAINT_VIOLATION = 5;
  30. public static final int CODE_UNCHARACTERIZED = 6;
  31. private static final String TOKEN_UNMAPPED_FIELD = "\\? (=|\\>|\\<|\\<\\>|!=|\\>=|\\<=|LIKE|BETWEEN) \\?";
  32. private static final long serialVersionUID = 1L;
  33. private String sql;
  34. private int iciqlCode;
  35. public IciqlException(Throwable t) {
  36. super(t.getMessage(), t);
  37. configureCode(t);
  38. }
  39. public IciqlException(String message, Object... parameters) {
  40. super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message);
  41. }
  42. public IciqlException(Throwable t, String message, Object... parameters) {
  43. super(parameters.length > 0 ? MessageFormat.format(message, parameters) : message, t);
  44. configureCode(t);
  45. }
  46. public static void checkUnmappedField(String sql) {
  47. if (Pattern.compile(IciqlException.TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {
  48. IciqlException e = new IciqlException("unmapped field in statement!");
  49. e.sql = sql;
  50. e.iciqlCode = CODE_UNMAPPED_FIELD;
  51. throw e;
  52. }
  53. }
  54. public static IciqlException fromSQL(String sql, Throwable t) {
  55. if (Pattern.compile(TOKEN_UNMAPPED_FIELD).matcher(sql).find()) {
  56. IciqlException e = new IciqlException(t, "unmapped field in statement!");
  57. e.sql = sql;
  58. e.iciqlCode = CODE_UNMAPPED_FIELD;
  59. return e;
  60. } else {
  61. IciqlException e = new IciqlException(t, t.getMessage());
  62. e.sql = sql;
  63. return e;
  64. }
  65. }
  66. public void setSQL(String sql) {
  67. this.sql = sql;
  68. }
  69. public String getSQL() {
  70. return sql;
  71. }
  72. public int getIciqlCode() {
  73. return iciqlCode;
  74. }
  75. private void configureCode(Throwable t) {
  76. if (t == null) {
  77. return;
  78. }
  79. if (t instanceof SQLException) {
  80. // http://developer.mimer.com/documentation/html_92/Mimer_SQL_Mobile_DocSet/App_Return_Codes2.html
  81. SQLException s = (SQLException) t;
  82. String state = s.getSQLState();
  83. if ("23000".equals(state)) {
  84. // MySQL duplicate primary key on insert
  85. iciqlCode = CODE_DUPLICATE_KEY;
  86. if (s.getErrorCode() == 1217) {
  87. iciqlCode = CODE_CONSTRAINT_VIOLATION;
  88. }
  89. } else if ("23505".equals(state)) {
  90. // Derby duplicate primary key on insert
  91. iciqlCode = CODE_DUPLICATE_KEY;
  92. } else if ("42000".equals(state)) {
  93. // MySQL duplicate unique index value on insert
  94. iciqlCode = CODE_DUPLICATE_KEY;
  95. } else if ("42Y07".equals(state)) {
  96. // Derby schema not found
  97. iciqlCode = CODE_OBJECT_NOT_FOUND;
  98. } else if ("42X05".equals(state)) {
  99. // Derby table not found
  100. iciqlCode = CODE_OBJECT_NOT_FOUND;
  101. } else if ("42Y55".equals(state)) {
  102. // Derby table not found
  103. iciqlCode = CODE_OBJECT_NOT_FOUND;
  104. } else if ("42S02".equals(state)) {
  105. // H2 table not found
  106. iciqlCode = CODE_OBJECT_NOT_FOUND;
  107. } else if ("42501".equals(state)) {
  108. // HSQL table not found
  109. iciqlCode = CODE_OBJECT_NOT_FOUND;
  110. } else if ("42P01".equals(state)) {
  111. // PostgreSQL table not found
  112. iciqlCode = CODE_OBJECT_NOT_FOUND;
  113. } else if ("X0X05".equals(state)) {
  114. // Derby view/table not found exists
  115. iciqlCode = CODE_OBJECT_NOT_FOUND;
  116. } else if ("X0Y32".equals(state)) {
  117. // Derby table already exists
  118. iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
  119. } else if ("42P07".equals(state)) {
  120. // PostgreSQL table or index already exists
  121. iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
  122. } else if ("42S01".equals(state)) {
  123. // MySQL view already exists
  124. iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
  125. } else if ("42S11".equals(state)) {
  126. // H2 index already exists
  127. iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
  128. } else if ("42504".equals(state)) {
  129. // HSQL index already exists
  130. iciqlCode = CODE_OBJECT_ALREADY_EXISTS;
  131. } else if ("2BP01".equals(state)) {
  132. // PostgreSQL constraint violation
  133. iciqlCode = CODE_CONSTRAINT_VIOLATION;
  134. } else if ("42533".equals(state)) {
  135. // HSQL constraint violation
  136. iciqlCode = CODE_CONSTRAINT_VIOLATION;
  137. } else if ("X0Y25".equals(state)) {
  138. // Derby constraint violation
  139. iciqlCode = CODE_CONSTRAINT_VIOLATION;
  140. } else if (s.getMessage().startsWith("[SQLITE")) {
  141. // SQLite error codes
  142. final String msg = s.getMessage();
  143. switch (s.getErrorCode()) {
  144. case 1:
  145. iciqlCode = CODE_OBJECT_NOT_FOUND;
  146. break;
  147. case 19:
  148. if (msg.contains("UNIQUE")) {
  149. iciqlCode = CODE_DUPLICATE_KEY;
  150. } else {
  151. iciqlCode = CODE_CONSTRAINT_VIOLATION;
  152. }
  153. break;
  154. default:
  155. iciqlCode = s.getErrorCode();
  156. break;
  157. }
  158. } else {
  159. // uncharacterized SQL code, we can always rely on iciqlCode != 0 in IciqlException
  160. iciqlCode = s.getErrorCode() == 0 ? CODE_UNCHARACTERIZED : s.getErrorCode();
  161. }
  162. }
  163. }
  164. @Override
  165. public String toString() {
  166. StringBuilder sb = new StringBuilder();
  167. sb.append(getClass().getName());
  168. String message = getLocalizedMessage();
  169. if (message != null) {
  170. sb.append(": ").append(message);
  171. }
  172. if (sql != null) {
  173. sb.append('\n').append(sql);
  174. }
  175. return sb.toString();
  176. }
  177. }