1   /*
2    * PRELYTIS.
3    * Copyright 2007, PRELYTIS S.A., and individual contributors
4    * as indicated by the @author tags. See the copyright.txt file in the
5    * distribution for a full listing of individual contributors.
6    *
7    * This is free software; you can redistribute it and/or modify it
8    * under the terms of the GNU Lesser General Public License as
9    * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */
22  package org.jdbc4olap.jdbc;
23  
24  import java.io.InputStream;
25  import java.io.Reader;
26  import java.math.BigDecimal;
27  import java.net.URL;
28  import java.sql.Array;
29  import java.sql.Blob;
30  import java.sql.Clob;
31  import java.sql.Date;
32  import java.sql.ParameterMetaData;
33  import java.sql.PreparedStatement;
34  import java.sql.Ref;
35  import java.sql.ResultSet;
36  import java.sql.ResultSetMetaData;
37  import java.sql.SQLException;
38  import java.sql.Time;
39  import java.sql.Timestamp;
40  import java.util.Calendar;
41  
42  import org.jdbc4olap.parsing.SimpleNode;
43  
44  /**
45   * @author <a href="mailto:fsiberchicot@jdbc4olap.org">Florian SIBERCHICOT</a>
46   * @author Dan Rollo
47   */
48  class OlapPreparedStatement extends OlapStatement implements PreparedStatement {
49  
50      private final String preparedStatement;
51      private String[] params;
52  
53      public OlapPreparedStatement(final OlapConnection c, final String statement) throws SQLException {
54          super(c);
55          //@TODO: empty query ? Maybe need to override OlapStatement.execute(String) methods to parse params, etc?
56          preparedStatement = statement;
57          final int nbParams = getStatementParameterCount(statement);
58          params = new String[nbParams];
59      }
60  
61      /**
62       * @param statement the sql of a prepared statement
63       * @return the number of occurences of the "?" (parameters) in the given statement string
64       */
65      static int getStatementParameterCount(final String statement) {
66          if (statement == null) {
67              return 0;
68          }
69  
70          int lastIndex = 0;
71          int nbParams = 0;
72          while (lastIndex != -1) {
73              lastIndex = statement.indexOf("?", lastIndex + 1);
74              if (lastIndex != -1) {
75                  nbParams++;
76              }
77          }
78          return nbParams;
79      }
80  
81      public void addBatch() throws SQLException {
82      }
83  
84      public void clearParameters() throws SQLException {
85          params = new String[preparedStatement.split("[?]").length - 1];
86      }
87  
88      private String prepareSql() throws SQLException {
89          String[] queryParts = preparedStatement.split("[?]");
90          StringBuffer sql = new StringBuffer();
91          for (int i = 0; i < queryParts.length; i++) {
92              if (i < params.length && params[i] == null) {
93                  throw new SQLException("Missing parameter");
94              }
95              sql.append(queryParts[i]).append(i < params.length ? params[i] : "");
96          }
97          return sql.toString();
98      }
99  
100     public boolean execute() throws SQLException {
101         final SimpleNode root = parseQuery(prepareSql());
102         prepareQueryMetaData(root);
103         resultSet = (OlapResultSet) processQuery(root);
104         resultSet.setMetaData(getResultSetMetaData(resultSet));
105         return true;
106     }
107 
108     public ResultSet executeQuery() throws SQLException {
109         final SimpleNode root = parseQuery(prepareSql());
110         prepareQueryMetaData(root);
111         resultSet = (OlapResultSet) processQuery(root);
112         resultSet.setMetaData(getResultSetMetaData(resultSet));
113         return resultSet;
114     }
115 
116     public int executeUpdate() throws SQLException {
117         throw new SQLException("jdbc4olap driver only supports SELECT queries");
118     }
119 
120     public ResultSetMetaData getMetaData() throws SQLException {
121         if (resultSet.getMetaData() == null) {
122             getResultSetMetaData(resultSet);
123         }
124         return resultSet.getMetaData();
125     }
126 
127     public ParameterMetaData getParameterMetaData() throws SQLException {
128         // TODO Auto-generated method stub
129         return null;
130     }
131 
132     public void setArray(final int arg0, final Array arg1) throws SQLException {
133         // TODO Auto-generated method stub
134     }
135 
136     public void setAsciiStream(final int arg0, final InputStream arg1, final int arg2) throws SQLException {
137         // TODO Auto-generated method stub
138     }
139 
140     public void setBigDecimal(final int arg0, final BigDecimal arg1) throws SQLException {
141         // TODO Auto-generated method stub
142     }
143 
144     public void setBinaryStream(final int arg0, final InputStream arg1, final int arg2) throws SQLException {
145         // TODO Auto-generated method stub
146     }
147 
148     public void setBlob(final int arg0, final Blob arg1) throws SQLException {
149         // TODO Auto-generated method stub
150     }
151 
152     public void setBoolean(final int arg0, final boolean arg1) throws SQLException {
153         // TODO Auto-generated method stub
154     }
155 
156     public void setByte(final int arg0, final byte arg1) throws SQLException {
157         // TODO Auto-generated method stub
158     }
159 
160     public void setBytes(final int arg0, final byte[] arg1) throws SQLException {
161         // TODO Auto-generated method stub
162     }
163 
164     public void setCharacterStream(final int arg0, final Reader arg1, final int arg2) throws SQLException {
165         // TODO Auto-generated method stub
166     }
167 
168     public void setClob(final int arg0, final Clob arg1) throws SQLException {
169         // TODO Auto-generated method stub
170     }
171 
172     public void setDate(final int arg0, final Date arg1) throws SQLException {
173         // TODO Auto-generated method stub
174     }
175 
176     public void setDate(final int arg0, final Date arg1, final Calendar arg2) throws SQLException {
177         // TODO Auto-generated method stub
178     }
179 
180     public void setDouble(final int arg0, final double arg1) throws SQLException {
181         if (arg0 > params.length) {
182             throw new SQLException("Incorrect index for parameter.");
183         }
184         //params[arg0] = Double.toString(arg1);
185         params[arg0 - 1] = Double.toString(arg1);
186     }
187 
188     public void setFloat(final int arg0, final float arg1) throws SQLException {
189         if (arg0 > params.length) {
190             throw new SQLException("Incorrect index for parameter.");
191         }
192         //params[arg0] = Float.toString(arg1);
193         params[arg0 - 1] = Float.toString(arg1);
194     }
195 
196     public void setInt(final int arg0, final int arg1) throws SQLException {
197         if (arg0 > params.length) {
198             throw new SQLException("Incorrect index for parameter.");
199         }
200         //params[arg0] = Integer.toString(arg1);
201         params[arg0 - 1] = Integer.toString(arg1);
202     }
203 
204     public void setLong(final int arg0, final long arg1) throws SQLException {
205         if (arg0 > params.length) {
206             throw new SQLException("Incorrect index for parameter.");
207         }
208         //params[arg0] = Long.toString(arg1);
209         params[arg0 - 1] = Long.toString(arg1);
210     }
211 
212     public void setNull(final int arg0, final int arg1) throws SQLException {
213         // TODO Auto-generated method stub
214     }
215 
216     public void setNull(final int arg0, final int arg1, final String arg2) throws SQLException {
217         // TODO Auto-generated method stub
218     }
219 
220     public void setObject(final int arg0, final Object arg1) throws SQLException {
221         if (arg0 > params.length) {
222             throw new SQLException("Incorrect index for parameter.");
223         }
224         //params[arg0]=arg1.toString();
225         params[arg0 - 1] = arg1.toString();
226     }
227 
228     public void setObject(final int arg0, final Object arg1, final int arg2) throws SQLException {
229         // TODO Auto-generated method stub
230     }
231 
232     public void setObject(final int arg0, final Object arg1, final int arg2, final int arg3) throws SQLException {
233         // TODO Auto-generated method stub
234     }
235 
236     public void setRef(final int arg0, final Ref arg1) throws SQLException {
237         // TODO Auto-generated method stub
238     }
239 
240     public void setShort(final int arg0, final short arg1) throws SQLException {
241         if (arg0 > params.length) {
242             throw new SQLException("Incorrect index for parameter.");
243         }
244         //params[arg0] = Short.toString(arg1);
245         params[arg0 - 1] = Short.toString(arg1);
246     }
247 
248     public void setString(final int arg0, final String arg1) throws SQLException {
249         if (arg0 > params.length) {
250             throw new SQLException("Incorrect index for parameter.");
251         }
252         //params[arg0] = arg1;
253         params[arg0 - 1] = "'" + arg1 + "'";
254     }
255 
256     public void setTime(final int arg0, final Time arg1) throws SQLException {
257         // TODO Auto-generated method stub
258     }
259 
260     public void setTime(final int arg0, final Time arg1, final Calendar arg2) throws SQLException {
261         // TODO Auto-generated method stub
262     }
263 
264     public void setTimestamp(final int arg0, final Timestamp arg1) throws SQLException {
265         // TODO Auto-generated method stub
266     }
267 
268     public void setTimestamp(final int arg0, final Timestamp arg1, final Calendar arg2) throws SQLException {
269         // TODO Auto-generated method stub
270     }
271 
272     public void setURL(final int arg0, final URL arg1) throws SQLException {
273         // TODO Auto-generated method stub
274     }
275 
276     public void setUnicodeStream(final int arg0, final InputStream arg1, final int arg2) throws SQLException {
277         // TODO Auto-generated method stub
278     }
279 
280 }