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.

SQLStatement.java 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * Copyright 2004-2011 H2 Group.
  3. * Copyright 2011 James Moger.
  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 com.iciql.util.JdbcUtils;
  19. import java.sql.PreparedStatement;
  20. import java.sql.ResultSet;
  21. import java.sql.SQLException;
  22. import java.util.ArrayList;
  23. import java.util.StringTokenizer;
  24. /**
  25. * This class represents a parameterized SQL statement.
  26. */
  27. public class SQLStatement {
  28. private Db db;
  29. private StringBuilder buff = new StringBuilder();
  30. private String sql;
  31. private ArrayList<Object> params = new ArrayList<Object>();
  32. SQLStatement(Db db) {
  33. this.db = db;
  34. }
  35. public void setSQL(String sql) {
  36. this.sql = sql;
  37. buff = new StringBuilder(sql);
  38. }
  39. public SQLStatement appendSQL(String s) {
  40. buff.append(s);
  41. sql = null;
  42. return this;
  43. }
  44. public SQLStatement appendTable(String schema, String table) {
  45. return appendSQL(db.getDialect().prepareTableName(schema, table));
  46. }
  47. public SQLStatement appendColumn(String column) {
  48. return appendSQL(db.getDialect().prepareColumnName(column));
  49. }
  50. /**
  51. * getSQL returns a simple string representation of the parameterized
  52. * statement which will be used later, internally, with prepareStatement.
  53. *
  54. * @return a simple sql statement
  55. */
  56. String getSQL() {
  57. if (sql == null) {
  58. sql = buff.toString();
  59. }
  60. return sql;
  61. }
  62. /**
  63. * toSQL creates a static sql statement with the referenced parameters
  64. * encoded in the statement.
  65. *
  66. * @return a complete sql statement
  67. */
  68. String toSQL() {
  69. if (sql == null) {
  70. sql = buff.toString();
  71. }
  72. if (params.size() == 0) {
  73. return sql;
  74. }
  75. StringBuilder sb = new StringBuilder();
  76. // TODO this needs to me more sophisticated
  77. StringTokenizer st = new StringTokenizer(sql, "?", false);
  78. int i = 0;
  79. while (st.hasMoreTokens()) {
  80. sb.append(st.nextToken());
  81. if (i < params.size()) {
  82. Object o = params.get(i);
  83. if (RuntimeParameter.PARAMETER == o) {
  84. // dynamic parameter
  85. sb.append('?');
  86. } else {
  87. // static parameter
  88. sb.append(db.getDialect().prepareStringParameter(o));
  89. }
  90. i++;
  91. }
  92. }
  93. return sb.toString();
  94. }
  95. public SQLStatement addParameter(Object o) {
  96. // Automatically convert java.util.Date to java.sql.Timestamp
  97. // if the dialect requires java.sql.Timestamp objects (e.g. Derby)
  98. if (o != null && o.getClass().equals(java.util.Date.class)
  99. && db.getDialect().getDateTimeClass().equals(java.sql.Timestamp.class)) {
  100. o = new java.sql.Timestamp(((java.util.Date) o).getTime());
  101. }
  102. params.add(o);
  103. return this;
  104. }
  105. void execute() {
  106. PreparedStatement ps = null;
  107. try {
  108. ps = prepare(false);
  109. ps.execute();
  110. } catch (SQLException e) {
  111. throw IciqlException.fromSQL(getSQL(), e);
  112. } finally {
  113. JdbcUtils.closeSilently(ps);
  114. }
  115. }
  116. ResultSet executeQuery() {
  117. try {
  118. return prepare(false).executeQuery();
  119. } catch (SQLException e) {
  120. throw IciqlException.fromSQL(getSQL(), e);
  121. }
  122. }
  123. int executeUpdate() {
  124. PreparedStatement ps = null;
  125. try {
  126. ps = prepare(false);
  127. return ps.executeUpdate();
  128. } catch (SQLException e) {
  129. throw IciqlException.fromSQL(getSQL(), e);
  130. } finally {
  131. JdbcUtils.closeSilently(ps);
  132. }
  133. }
  134. long executeInsert() {
  135. PreparedStatement ps = null;
  136. try {
  137. ps = prepare(true);
  138. ps.executeUpdate();
  139. long identity = -1;
  140. ResultSet rs = ps.getGeneratedKeys();
  141. if (rs != null && rs.next()) {
  142. identity = rs.getLong(1);
  143. }
  144. JdbcUtils.closeSilently(rs);
  145. return identity;
  146. } catch (SQLException e) {
  147. throw IciqlException.fromSQL(getSQL(), e);
  148. } finally {
  149. JdbcUtils.closeSilently(ps);
  150. }
  151. }
  152. private void setValue(PreparedStatement prep, int parameterIndex, Object x) {
  153. try {
  154. prep.setObject(parameterIndex, x);
  155. } catch (SQLException e) {
  156. IciqlException ix = new IciqlException(e, "error setting parameter {0} as {1}", parameterIndex, x
  157. .getClass().getSimpleName());
  158. ix.setSQL(getSQL());
  159. throw ix;
  160. }
  161. }
  162. PreparedStatement prepare(boolean returnGeneratedKeys) {
  163. PreparedStatement prep = db.prepare(getSQL(), returnGeneratedKeys);
  164. for (int i = 0; i < params.size(); i++) {
  165. Object o = params.get(i);
  166. setValue(prep, i + 1, o);
  167. }
  168. return prep;
  169. }
  170. }