001 package hep.aida.ref.sql;
002
003 // FreeHEP
004 import hep.aida.ref.tuple.AbstractTuple;
005 import hep.aida.ref.tuple.TupleColumn;
006 import hep.aida.ref.tuple.FTupleColumn;
007 import hep.aida.ref.tuple.FTupleCursor;
008 import org.freehep.util.Value;
009
010 // Log4J
011 import org.apache.log4j.Logger;
012
013 // AIDA
014 import hep.aida.ITuple;
015 import hep.aida.IBaseTupleColumn;
016 import hep.aida.ICloud1D;
017 import hep.aida.ICloud2D;
018 import hep.aida.ICloud3D;
019 import hep.aida.IHistogram1D;
020 import hep.aida.IHistogram2D;
021 import hep.aida.IHistogram3D;
022 import hep.aida.IProfile1D;
023 import hep.aida.IProfile2D;
024 import hep.aida.IEvaluator;
025 import hep.aida.IFilter;
026
027 // SQL
028 import java.sql.PreparedStatement;
029 import java.sql.ResultSet;
030 import java.sql.ResultSetMetaData;
031 import java.sql.SQLException;
032
033 // Java
034 import java.util.Collection;
035 import java.util.ArrayList;
036 import java.lang.reflect.Constructor;
037 import java.lang.reflect.InvocationTargetException;
038
039 /** <code>SQLTuple</code> is an extension of {@link ITuple}
040 * for SQL database.
041 * <br>
042 * <code>SQLTuple</code> contains several extensions to {@link ITuple}
043 * and {@link ITuple}:
044 * <ul>
045 * <li><code>void addIndex(String[] columnName);</code></li>
046 * <li><code>void addColumn(String columnName, Class columnType, IEvaluator evaluator);</code></li>
047 * <li><code>void start(IFilter filter);</code></li>
048 * <li><code>void start(String[] columns);</code></li>
049 * <li><code>void start(IFilter filter, String[] columns);</code></li>
050 * <li><code>void start(String stmtSrc);</code></li>
051 * <li><code>void start(IFilter filter, String stmtSrc);</code></li>
052 * <li><code>String[] getRowData();</code></li>
053 * <li><code>boolean getBoolean(String column);</code></li>
054 * <li><code>byte getByte(String column);</code></li>
055 * <li><code>char getChar(String column);</code></li>
056 * <li><code>short getShort(String column);</code></li>
057 * <li><code>int getInt(String column);</code></li>
058 * <li><code>long getLong(String column);</code></li>
059 * <li><code>float getFloat(String column);</code></li>
060 * <li><code>double getDouble(String column);</code></li>
061 * <li><code>String getString(String column);</code></li>
062 * <li><code>Object getObject(String column);</code></li>
063 * <li><code>ITuple getTuple(String column);</code></li>
064 * <li><code>void fill(String column, boolean value);</code></li>
065 * <li><code>void fill(String column, byte value);</code></li>
066 * <li><code>void fill(String column, char value);</code></li>
067 * <li><code>void fill(String column, short value);</code></li>
068 * <li><code>void fill(String column, int value);</code></li>
069 * <li><code>void fill(String column, long value);</code></li>
070 * <li><code>void fill(String column, float value);</code></li>
071 * <li><code>void fill(String column, double value);</code></li>
072 * <li><code>void fill(String column, String value);</code></li>
073 * <li><code>void fill(String column, Object value);</code></li>
074 * <li><code>void fill(String column, ITuple value);</code></li>
075 * <li><code>double groupValue(String operator, int column);</code></li>
076 * <li><code>String columnDefault(int param);</code></li>
077 * <li><code>String[] columnDefaults();</code></li>
078 * <li><code>Collection<String> getColumn(String cName);</code></li>
079 * <li><code><T> Collection<T> getColumn(String cName, Class<T> cl);</code></li>
080 * <li><code>Collection<String> getColumn(String cName, IFilter filter);</code></li>
081 * <li><code><T> Collection<T> getColumn(String cName, Class<T> cl, IFilter filter);</code></li>
082 * </ul>
083 * <p><font color="#880088">
084 * <pre>
085 * $Log: SQLTuple.java,v $
086 * Revision 1.82 2007/05/23 16:38:44 hrivnac
087 * logical connections for Plotter; better UML
088 *
089 * Revision 1.81 2006/12/15 00:16:13 hrivnac
090 * FORWARD_ONLY allows to plot big ntuples
091 *
092 * Revision 1.80 2006/12/12 15:21:42 hrivnac
093 * McKoi replaced with Derby; uppercase-only dbs handled better; moving to JAS 0.8.3
094 *
095 * Revision 1.79 2006/11/22 23:55:36 hrivnac
096 * fixed non-double values, added intr database
097 *
098 * Revision 1.78 2006/11/20 16:56:08 hrivnac
099 * fixing input params for Plotter command line
100 *
101 * Revision 1.77 2006/11/17 17:11:34 hrivnac
102 * chooser.jsp closes tree too
103 *
104 * Revision 1.76 2006/11/15 16:16:01 hrivnac
105 * Oracle work fine in CERN, cache enabled
106 *
107 * Revision 1.75 2006/11/14 16:06:18 hrivnac
108 * improving Web Service
109 *
110 * Revision 1.74 2006/10/12 15:02:58 hrivnac
111 * bug fixes
112 *
113 * Revision 1.73 2005/09/28 18:22:42 hrivnac
114 * javadoc fixed
115 *
116 * Revision 1.72 2005/09/28 16:21:06 hrivnac
117 * code cleaning
118 *
119 * Revision 1.71 2005/09/21 23:00:38 hrivnac
120 * readonly tuples can be read
121 *
122 * Revision 1.70 2005/09/21 14:49:49 hrivnac
123 * better support for Oracle types
124 *
125 * Revision 1.69 2005/09/19 14:30:12 hrivnac
126 * projection bugs fixed
127 *
128 * Revision 1.68 2005/09/02 14:10:31 hrivnac
129 * moved to JAS3 0.8.2
130 *
131 * Revision 1.67 2005/06/15 15:26:04 hrivnac
132 * ITuple._rows only evaluated when requested
133 *
134 * Revision 1.66 2005/03/18 12:12:11 hrivnac
135 * ITuple.start() resets ITuple to its original shape even after customised ITuple.start(...) calls
136 *
137 * Revision 1.65 2005/03/09 15:25:52 hrivnac
138 * ITuple.rows() improved
139 *
140 * Revision 1.64 2005/03/08 17:05:51 hrivnac
141 * ...
142 *
143 * Revision 1.63 2005/02/10 20:07:51 hrivnac
144 * bug fixes to support new ColMan
145 *
146 * Revision 1.62 2005/01/27 17:30:41 hrivnac
147 * PreparedStatement with default values
148 *
149 * Revision 1.61 2005/01/25 16:45:03 hrivnac
150 * Adding rows uses PreparedStatement
151 *
152 * Revision 1.60 2004/12/01 16:07:15 hrivnac
153 * better support for ColMan JAS3 plugin
154 *
155 * Revision 1.59 2004/11/30 14:06:04 hrivnac
156 * SQLTuple.rows() fix
157 *
158 * Revision 1.58 2004/10/29 22:27:25 hrivnac
159 * imports corrected
160 *
161 * Revision 1.57 2004/10/21 15:46:49 hrivnac
162 * doc improved
163 *
164 * Revision 1.56 2004/10/20 23:02:29 hrivnac
165 * Types mapping simplified
166 *
167 * Revision 1.55 2004/10/13 12:25:39 hrivnac
168 * defaults work fine
169 *
170 * Revision 1.54 2004/10/13 09:21:21 hrivnac
171 * defaults used
172 *
173 * Revision 1.53 2004/10/12 13:25:40 hrivnac
174 * small improvements
175 *
176 * Revision 1.52 2004/10/08 15:22:33 hrivnac
177 * JAS3 plugin works
178 *
179 * Revision 1.51 2004/07/06 14:24:50 hrivnac
180 * support for Oracle
181 *
182 * Revision 1.50 2004/06/30 13:01:05 hrivnac
183 * oracle sceleton
184 *
185 * Revision 1.49 2004/06/23 08:04:53 hrivnac
186 * documentation fixes
187 *
188 * Revision 1.48 2004/06/18 09:17:31 hrivnac
189 * StmtSrc can be accessed directkly
190 *
191 * Revision 1.47 2004/06/16 21:56:43 hrivnac
192 * StringBuffer in SQLTuple.addRow() -> speed
193 *
194 * Revision 1.46 2004/05/22 15:12:59 hrivnac
195 * class id reformated
196 *
197 * Revision 1.45 2004/05/04 08:50:33 hrivnac
198 * can run with JAS3
199 *
200 * Revision 1.44 2004/05/03 19:22:30 hrivnac
201 * basic support for JAS3
202 *
203 * Revision 1.43 2004/04/21 13:41:32 hrivnac
204 * explicit dependency on MySQL removed
205 *
206 * Revision 1.42 2004/04/21 08:24:50 hrivnac
207 * some explicit MySQL dependencies removed
208 *
209 * Revision 1.41 2004/04/20 12:46:49 hrivnac
210 * tuples use always primitive types
211 *
212 * Revision 1.40 2004/04/15 08:49:01 hrivnac
213 * ColMan fixes
214 *
215 * Revision 1.39 2004/04/14 13:54:41 hrivnac
216 * potential bugs fixed
217 *
218 * Revision 1.38 2004/04/14 13:39:47 hrivnac
219 * 1.5 warnings fixed
220 *
221 * Revision 1.37 2004/04/13 15:45:54 hrivnac
222 * AIDA URL introduced
223 *
224 * Revision 1.36 2004/02/10 14:50:58 hrivnac
225 * JavaDoc tags completed
226 *
227 * Revision 1.35 2004/02/04 13:30:39 hrivnac
228 * - improvement of Enums internal mapping
229 * - general cleaning
230 *
231 * Revision 1.34 2003/11/24 15:13:22 hrivnac
232 * Logging improved.
233 *
234 * Revision 1.33 2003/11/20 17:21:58 hrivnac
235 * Java 1.5 natively supported, Log4J reporting improved.
236 *
237 * Revision 1.32 2003/11/17 15:01:12 hrivnac
238 * More BM results.
239 *
240 * Revision 1.31 2003/11/17 10:18:29 hrivnac
241 * Cleaning.
242 *
243 * Revision 1.30 2003/11/13 18:19:38 hrivnac
244 * BenchMarks running for all DBs, Reporting class added.
245 *
246 * Revision 1.29 2003/11/13 15:43:08 hrivnac
247 * BenchMarking introduced.
248 *
249 * Revision 1.28 2003/11/13 11:07:31 hrivnac
250 * EventSelector prototype added.
251 *
252 * Revision 1.27 2003/11/05 19:46:22 hrivnac
253 * - FreeHEP 1.2.1
254 * - JAIDA 3.2.1
255 *
256 * Revision 1.18 2003/10/30 11:42:40 hrivnac
257 * ArrayList -> Collection
258 *
259 * Revision 1.15 2003/10/22 17:59:39 hrivnac
260 * Refactored.
261 *
262 * Revision 1.13 2003/10/21 13:56:00 hrivnac
263 * Default values supported.
264 *
265 * Revision 1.12 2003/10/21 13:24:52 hrivnac
266 * Constructor from columnString implemented.
267 *
268 * Revision 1.11 2003/10/10 10:12:21 hrivnac
269 * All three testing pgms work.
270 *
271 * Revision 1.8 2003/10/07 10:15:57 hrivnac
272 * SQL extensions to ITuple added.
273 *
274 * Revision 1.5 2003/10/03 16:02:21 hrivnac
275 * Better handling of multiple technologies.
276 *
277 * Revision 1.3 2003/10/02 14:24:01 hrivnac
278 * Cleaning.
279 *
280 * Revision 1.7 2003/09/30 20:30:47 hrivnac
281 * special Pool functions
282 *
283 * Revision 1.6 2003/09/30 16:46:02 hrivnac
284 * - Writing test in TestWrite
285 * - SQLTuple projections supported
286 *
287 * Revision 1.5 2003/09/30 14:11:48 hrivnac
288 * Can created SQLTuples.
289 *
290 * Revision 1.4 2003/09/30 12:29:19 hrivnac
291 * Tuples can be written.
292 *
293 * Revision 1.3 2003/09/29 16:15:54 hrivnac
294 * More complete.
295 *
296 * Revision 1.2 2003/09/29 14:36:40 hrivnac
297 * Works per attribute.
298 *
299 * </pre>
300 * </font></p>
301 * @opt attributes
302 * @opt operations
303 * @opt types
304 * @opt visibility
305 * @version $Id: SQLTuple.java,v 1.82 2007/05/23 16:38:44 hrivnac Exp $
306 * @author <a href="mailto:Julius.Hrivnac@cern.ch">J.Hrivnac</a> */
307 public class SQLTuple extends AbstractTuple {
308
309 /** Just call superclass constructor.
310 * @param name The name of the ITuple.
311 * @param title The title of the ITuple.
312 * @param columnName The names of columns.
313 * @param columnType The types of columns.
314 * @param options The options to be used to create the ITuple. */
315 public SQLTuple(String name,
316 String title,
317 String[] columnName,
318 Class[] columnType,
319 String options) {
320 super(name, title, options);
321 initSQLTuple(name, title, columnName, columnType, options);
322 }
323
324 /** Just calls superclass constructor.
325 * @param name The name of the ITuple.
326 * @param title The title of the ITuple.
327 * @param columnsString The columns definition.
328 * @param options The options to be used to create the ITuple. */
329 public SQLTuple(String name,
330 String title,
331 String columnsString,
332 String options) {
333 super(name, title, options);
334 initSQLTuple(name, title, super.columnNames(), super.columnTypes(), options);
335 }
336
337 /** Initialise internal variables. Is called from the constructor.
338 * @param name The name of the ITuple.
339 * @param title The title of the ITuple.
340 * @param columnName The names of columns.
341 * @param columnType The types of columns.
342 * @param options The options to be used to create the ITuple.
343 * @throws IllegalArgumentException if the ITuple can't be created. */
344 protected void initSQLTuple(String name,
345 String title,
346 String[] columnName,
347 Class[] columnType,
348 String options) throws IllegalArgumentException {
349 try {
350 setOptions(options);
351 _names = columnName;
352 _types = columnType;
353 _defaults = new String[ _names.length];
354 _defaultObjects = new Object[ _names.length];
355 _filled = new boolean[_names.length];
356 int eq;
357 for (int i = 0; i < _names.length; i++) {
358 _defaults[i] = null;
359 eq = columnName[i].indexOf("=");
360 if (eq > -1) {
361 _defaults[i] = _names[i].substring(eq + 1 ).trim();
362 _names[i] = _names[i].substring(0 , eq).trim();
363 _defaultObjects[i] = type2Object(_defaults[i], _types[i]);
364 }
365 }
366 _namesOrig = _names;
367 _typesOrig = _types;
368 _defaultsOrig = _defaults;
369 _defaultObjectsOrig = _defaultObjects;
370 _stmtSrc = new StmtSrc(_accessor, title);
371 prepare();
372 _rows = -1;
373 }
374 catch (SQLTupleException e) {
375 throw new IllegalArgumentException("Can't initialise SQLTuple " + name + " / " + title, e);
376 }
377
378 }
379
380 /** <code>SQLTuple</code> extension: add indexes into SQL table.
381 * @param columnName The array of column names to be indexed. */
382 public void addIndex(String[] columnName) {
383 for (String name : columnName) {
384 String[] args = {"index_" + title() + "_" + name, name};
385 update("addIndex", args);
386 }
387 }
388
389 /** <code>SQLTuple</code> extension: add column into SQL table.
390 * @param columnName The name of column to be added.
391 * @param columnType The type of column to be added.
392 * @param evaluator The evaluator to be used to compute new column values. */
393 public void addColumn(String columnName,
394 Class columnType,
395 IEvaluator evaluator) {
396 // Check whether it is a new column
397 for (int i = 0; i < columns(); i++) {
398 if (columnName.equals(_names[i])) {
399 log.warn("Column " + columnName + " already exists");
400 return;
401 }
402 }
403 // Add column into table
404 String[] args1 = {columnName, _accessor.sqlName(columnType)};
405 update("addColumnAlter", args1);
406 // Fill table with values
407 String[] args2 = {columnName, evaluator.expression()};
408 update("addColumnUpdate", args2);
409 // Update internal variables
410 String[] names0 = new String[columns() + 1];
411 String[] defaults0 = new String[columns() + 1];
412 Object[] defaultObjects0 = new Object[columns() + 1];
413 Class[] types0 = new Class[ columns() + 1];
414 _filled = new boolean[columns() + 1];
415 for (int i = 0; i < columns(); i++) {
416 names0[ i] = _names[ i];
417 defaults0[i] = _defaults[ i];
418 defaultObjects0[i] = _defaultObjects[i];
419 types0[ i] = _types[ i];
420 }
421 names0[ columns()] = columnName;
422 defaults0[columns()] = null;
423 defaultObjects0[columns()] = type2Object(null, columnType);
424 types0[ columns()] = columnType;
425 _names = names0;
426 _defaults = defaults0;
427 _defaultObjects = defaultObjects0;
428 _types = types0;
429 for (int i = 0; i < columns(); i++) {
430 _filled[i] = false;;
431 }
432 }
433
434 /** <code>SQLTuple</code> is never in memory => false.
435 * @return <code>false</code>. */
436 public boolean isInMemory() {
437 return false;
438 }
439
440 /** Use SQL <code>min<code> function.
441 * @param column The column to get the minimum of.
442 * @return The found minimum. */
443 public double columnMin(int column) {
444 return groupValue("min", column);
445 }
446
447 /** Use SQL <code>max<code> function.
448 * @param column The column to get the maximum of.
449 * @return The found maximum. */
450 public double columnMax(int column) {
451 return groupValue("max", column);
452 }
453
454 /** Use SQL <code>avg<code> function.
455 * @param column The column to get the average of.
456 * @return The found average. */
457 public double columnMean(int column) {
458 return groupValue("avg", column);
459 }
460
461 /** Use SQL <code>std<code> function.
462 * @param column The column to get the std of.
463 * @return The found std. */
464 public double columnRms(int column) {
465 return groupValue("std", column);
466 }
467
468 /** Apply an operator to a column.
469 * @param operator The operator to be applied..
470 * @param column The column to be evalated.
471 * @return The found result of the operator applied on the column.
472 * @throws IllegalArgumentException if the operator can't be applied on the column. */
473 private double groupValue(String operator, int column) {
474 String[] args = {operator, columnName(column)};
475 ResultSet rs = query("groupValue", args);
476 try {
477 rs.next();
478 }
479 catch (SQLException e) {
480 log.error(Util.report("Can't perform operation " + operator + " on column " + column, e), e);
481 throw new IllegalArgumentException("Couldn't perform operation " + operator + " on column " + column, e);
482 }
483 return getDouble(rs, 1);
484 }
485
486 /** Apply an operator to a column.
487 * @param operator The operator to be applied..
488 * @param column The column formula to be evalated.
489 * @return The found result of the operator applied on the column.
490 * @throws IllegalArgumentException if the operator can't be applied on the column. */
491 public double groupValue(String operator, String column) {
492 String[] args = {operator, column};
493 ResultSet rs = query("groupValue", args);
494 try {
495 rs.next();
496 }
497 catch (SQLException e) {
498 log.error(Util.report("Can't perform operation " + operator + " on formula " + column, e), e);
499 throw new IllegalArgumentException("Couldn't perform operation " + operator + " on formula " + column, e);
500 }
501 return getDouble(rs, 1);
502 }
503
504 /** Find column number from the column name.
505 * @param name The name of the column.
506 * @return The number of the specified column.
507 * @throws IllegalArgumentException if no column of that name exists. */
508 public int findColumn(String name) throws IllegalArgumentException {
509 if (_accessor.supportsOnlyUpperCase()) {
510 name = name.toUpperCase();
511 }
512 for (int i = 0; i < _names.length; i++) {
513 if (_names[i].equals(name)) {
514 return i;
515 }
516 }
517 throw new IllegalArgumentException("There is no column " + name);
518 }
519
520 /** Get boolean value of a column.
521 * @param column The column name.
522 * @return The value of the current row. */
523 public boolean getBoolean(String column) {
524 return getBoolean(findColumn(column));
525 }
526
527 /** Get boolean value of a column.
528 * @param column The column number.
529 * @return The value of the current row. */
530 public boolean getBoolean(int column) {
531 try {
532 return _rs.getBoolean(column+1);
533 }
534 catch (SQLException e) {
535 log.error(Util.report("Can't get boolean of column " + column + ", return default", e), e);
536 }
537 return Boolean.parseBoolean(_defaults[column]);
538 }
539
540 /** Get byte value of a column.
541 * @param column The column name.
542 * @return The value of the current row. */
543 public byte getByte(String column) {
544 return getByte(findColumn(column));
545 }
546
547 /** Get byte value of a column.
548 * @param column The column number.
549 * @return The value of the current row. */
550 public byte getByte(int column) {
551 try {
552 return _rs.getByte(column+1);
553 }
554 catch (SQLException e) {
555 log.error(Util.report("Can't get byte of column " + column + ", return default", e), e);
556 }
557 return Byte.parseByte(_defaults[column]);
558 }
559
560 /** Get char value of a column.
561 * @param column The column name.
562 * @return The value of the current row. */
563 public char getChar(String column) {
564 return getChar(findColumn(column));
565 }
566
567 /** Get char value of a column.
568 * @param column The column number.
569 * @return The value of the current row. */
570 public char getChar(int column) {
571 try {
572 return _rs.getString(column+1).charAt(0);
573 }
574 catch (SQLException e) {
575 log.error(Util.report("Can't get char of column " + column + ", return default", e), e);
576 }
577 return _defaults[column].toCharArray()[0];
578 }
579
580 /** Get double value of a column.
581 * @param column The column name.
582 * @return The value of the current row. */
583 public double getDouble(String column) {
584 return getDouble(findColumn(column));
585 }
586
587 /** Get double value of a column.
588 * @param column The column number.
589 * @return The value of the current row. */
590 public double getDouble(int column) {
591 try {
592 return _rs.getDouble(column+1);
593 }
594 catch (SQLException e) {
595 log.error(Util.report("Can't get double of column " + column + ", return default", e), e);
596 }
597 return Double.parseDouble(_defaults[column]);
598 }
599
600 /** Get float value of a column.
601 * @param column The column name.
602 * @return The value of the current row. */
603 public float getFloat(String column) {
604 return getFloat(findColumn(column));
605 }
606
607 /** Get float value of a column.
608 * @param column The column number.
609 * @return The value of the current row. */
610 public float getFloat(int column) {
611 try {
612 return _rs.getFloat(column+1);
613 }
614 catch (SQLException e) {
615 log.error(Util.report("Can't get double of column " + column + ", return default", e), e);
616 }
617 return Float.parseFloat(_defaults[column]);
618 }
619
620 /** Get int value of a column.
621 * @param column The column name.
622 * @return The value of the current row. */
623 public int getInt(String column) {
624 return getInt(findColumn(column));
625 }
626
627 /** Get int value of a column.
628 * @param column The column number.
629 * @return The value of the current row. */
630 public int getInt(int column) {
631 try {
632 return _rs.getInt(column+1);
633 }
634 catch (SQLException e) {
635 log.error(Util.report("Can't get int of column " + column + ", return default", e), e);
636 }
637 return Integer.parseInt(_defaults[column]);
638 }
639
640 /** Get long value of a column.
641 * @param column The column name.
642 * @return The value of the current row. */
643 public long getLong(String column) {
644 return getLong(findColumn(column));
645 }
646
647 /** Get long value of a column.
648 * @param column The column number.
649 * @return The value of the current row. */
650 public long getLong(int column) {
651 try {
652 return _rs.getLong(column+1);
653 }
654 catch (SQLException e) {
655 log.error(Util.report("Can't get long of column " + column + ", return default", e), e);
656 }
657 return Long.parseLong(_defaults[column]);
658 }
659
660 /** Get Object value of a column.
661 * @param column The column name.
662 * @return The value of the current row. */
663 public Object getObject(String column) {
664 return getObject(findColumn(column));
665 }
666
667 /** Get Object value of a column.
668 * @param column The column number.
669 * @return The value of the current row. */
670 public Object getObject(int column) {
671 try {
672 return _rs.getObject(column+1);
673 }
674 catch (SQLException e) {
675 log.error(Util.report("Can't get Object of column " + column + ", return default String", e), e);
676 }
677 return _defaults[column];
678 }
679
680 /** Get short value of a column.
681 * @param column The column name.
682 * @return The value of the current row. */
683 public short getShort(String column) {
684 return getShort(findColumn(column));
685 }
686
687 /** Get short value of a column.
688 * @param column The column number.
689 * @return The value of the current row. */
690 public short getShort(int column) {
691 try {
692 return _rs.getShort(column+1);
693 }
694 catch (SQLException e) {
695 log.error(Util.report("Can't get short of column " + column + ", return default", e), e);
696 }
697 return Short.parseShort(_defaults[column]);
698 }
699
700 /** Get String value of a column.
701 * @param column The column name.
702 * @return The value of the current row. */
703 public String getString(String column) {
704 return getString(findColumn(column));
705 }
706
707 /** Get String value of a column.
708 * @param column The column number.
709 * @return The value of the current row. */
710 public String getString(int column) {
711 try {
712 return _rs.getString(column+1);
713 }
714 catch (SQLException e) {
715 log.error(Util.report("Can't get String of column " + column + ", return default", e), e);
716 }
717 return _defaults[column];
718 }
719
720 /** Get ITuple value of a column.
721 * @param column The column name.
722 * @return The value of the current row. */
723 public ITuple getTuple(String column) {
724 return getTuple(findColumn(column));
725 }
726
727 /** Fill {@link Value} in a column.
728 * @param column The column name.
729 * @param value The {@link Value} to be filled in the current row.
730 * @throws IllegalArgumentException if {@link Value} can't be filled. */
731 public void fill(int column, Value value) throws IllegalArgumentException {
732 if (_readOnly) {
733 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
734 }
735 try {
736 _statement.setString(column+1, value.getString());
737 }
738 catch (SQLException e) {
739 log.error(Util.report("Can't set column " + column + " to value " + value, e), e);
740 throw new IllegalArgumentException("Couldn't column " + column + " to value " + value, e);
741 }
742 _filled[column] = true;
743 }
744
745 /** Fill int value in a column.
746 * @param column The column name.
747 * @param value The value to be filled in the current row.
748 * @throws IllegalArgumentException if value can't be filled. */
749 public void fill(String column, int value) throws IllegalArgumentException {
750 fill(findColumn(column), value);
751 }
752
753 /** Fill int value in a column.
754 * @param column The column number.
755 * @param value The value to be filled in the current row.
756 * @throws IllegalArgumentException if value can't be filled. */
757 public void fill(int column, int value) throws IllegalArgumentException {
758 if (_readOnly) {
759 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
760 }
761 try {
762 _statement.setInt(column+1, value);
763 }
764 catch (SQLException e) {
765 log.error(Util.report("Can't set column " + column + " to int value " + value, e), e);
766 throw new IllegalArgumentException("Couldn't column " + column + " to int value " + value, e);
767 }
768 _filled[column] = true;
769 }
770
771 /** Fill short value in a column.
772 * @param column The column name.
773 * @param value The value to be filled in the current row.
774 * @throws IllegalArgumentException if value can't be filled. */
775 public void fill(String column, short value) throws IllegalArgumentException {
776 fill(findColumn(column), value);
777 }
778
779 /** Fill short value in a column.
780 * @param column The column number.
781 * @param value The value to be filled in the current row.
782 * @throws IllegalArgumentException if value can't be filled. */
783 public void fill(int column, short value) throws IllegalArgumentException {
784 if (_readOnly) {
785 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
786 }
787 try {
788 _statement.setShort(column+1, value);
789 }
790 catch (SQLException e) {
791 log.error(Util.report("Can't set column " + column + " to short value " + value, e), e);
792 throw new IllegalArgumentException("Couldn't column " + column + " to short value " + value, e);
793 }
794 _filled[column] = true;
795 }
796
797 /** Fill long value in a column.
798 * @param column The column name.
799 * @param value The value to be filled in the current row.
800 * @throws IllegalArgumentException if value can't be filled. */
801 public void fill(String column, long value) throws IllegalArgumentException {
802 fill(findColumn(column), value);
803 }
804
805 /** Fill long value in a column.
806 * @param column The column number.
807 * @param value The value to be filled in the current row.
808 * @throws IllegalArgumentException if value can't be filled. */
809 public void fill(int column, long value) throws IllegalArgumentException {
810 if (_readOnly) {
811 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
812 }
813 try {
814 _statement.setLong(column+1, value);
815 }
816 catch (SQLException e) {
817 log.error(Util.report("Can't set column " + column + " to long value " + value, e), e);
818 throw new IllegalArgumentException("Couldn't column " + column + " to long value " + value, e);
819 }
820 _filled[column] = true;
821 }
822
823 /** Fill double value in a column.
824 * @param column The column name.
825 * @param value The value to be filled in the current row.
826 * @throws IllegalArgumentException if value can't be filled. */
827 public void fill(String column, double value) throws IllegalArgumentException {
828 fill(findColumn(column), value);
829 }
830
831 /** Fill double value in a column.
832 * @param column The column number.
833 * @param value The value to be filled in the current row.
834 * @throws IllegalArgumentException if value can't be filled. */
835 public void fill(int column, double value) throws IllegalArgumentException {
836 if (_readOnly) {
837 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
838 }
839 try {
840 _statement.setDouble(column+1, value);
841 }
842 catch (SQLException e) {
843 log.error(Util.report("Can't set column " + column + " to double value " + value, e), e);
844 throw new IllegalArgumentException("Couldn't column " + column + " to double value " + value, e);
845 }
846 _filled[column] = true;
847 }
848
849 /** Fill float value in a column.
850 * @param column The column name.
851 * @param value The value to be filled in the current row.
852 * @throws IllegalArgumentException if value can't be filled. */
853 public void fill(String column, float value) throws IllegalArgumentException {
854 fill(findColumn(column), value);
855 }
856
857 /** Fill float value in a column.
858 * @param column The column number.
859 * @param value The value to be filled in the current row.
860 * @throws IllegalArgumentException if value can't be filled. */
861 public void fill(int column, float value) throws IllegalArgumentException {
862 if (_readOnly) {
863 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
864 }
865 try {
866 _statement.setFloat(column+1, value);
867 }
868 catch (SQLException e) {
869 log.error(Util.report("Can't set column " + column + " to float value " + value, e), e);
870 throw new IllegalArgumentException("Couldn't column " + column + " to float value " + value, e);
871 }
872 _filled[column] = true;
873 }
874
875 /** Fill boolean value in a column.
876 * @param column The column name.
877 * @param value The value to be filled in the current row.
878 * @throws IllegalArgumentException if value can't be filled. */
879 public void fill(String column, boolean value) throws IllegalArgumentException {
880 fill(findColumn(column), value);
881 }
882
883 /** Fill boolean value in a column.
884 * @param column The column number
885 * @param value The value to be filled in the current row.
886 * @throws IllegalArgumentException if value can't be filled. */
887 public void fill(int column, boolean value) throws IllegalArgumentException {
888 if (_readOnly) {
889 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
890 }
891 try {
892 _statement.setBoolean(column+1, value);
893 }
894 catch (SQLException e) {
895 log.error(Util.report("Can't set column " + column + " to boolean value " + value, e), e);
896 throw new IllegalArgumentException("Couldn't column " + column + " to boolean value " + value, e);
897 }
898 _filled[column] = true;
899 }
900
901 /** Fill byte value in a column.
902 * @param column The column name
903 * @param value The value to be filled in the current row.
904 * @throws IllegalArgumentException if value can't be filled. */
905 public void fill(String column, byte value) throws IllegalArgumentException {
906 fill(findColumn(column), value);
907 }
908
909 /** Fill byte value in a column.
910 * @param column The column number.
911 * @param value The value to be filled in the current row.
912 * @throws IllegalArgumentException if value can't be filled. */
913 public void fill(int column, byte value) throws IllegalArgumentException {
914 if (_readOnly) {
915 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
916 }
917 try {
918 _statement.setByte(column+1, value);
919 }
920 catch (SQLException e) {
921 log.error(Util.report("Can't set column " + column + " to byte value " + value, e), e);
922 throw new IllegalArgumentException("Couldn't column " + column + " to byte value " + value, e);
923 }
924 _filled[column] = true;
925 }
926
927 /** Fill char value in a column.
928 * @param column The column name.
929 * @param value The value to be filled in the current row.
930 * @throws IllegalArgumentException if value can't be filled. */
931 public void fill(String column, char value) throws IllegalArgumentException {
932 fill(findColumn(column), value);
933 }
934
935 /** Fill char value in a column.
936 * @param column The column number.
937 * @param value The value to be filled in the current row.
938 * @throws IllegalArgumentException if value can't be filled. */
939 public void fill(int column, char value) throws IllegalArgumentException {
940 if (_readOnly) {
941 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
942 }
943 try {
944 _statement.setString(column+1, Character.toString(value));
945 }
946 catch (SQLException e) {
947 log.error(Util.report("Can't set column " + column + " to char value " + value, e), e);
948 throw new IllegalArgumentException("Couldn't column " + column + " to char value " + value, e);
949 }
950 _filled[column] = true;
951 }
952
953 /** Fill String value in a column.
954 * @param column The column name.
955 * @param value The value to be filled in the current row.
956 * @throws IllegalArgumentException if value can't be filled. */
957 public void fill(String column, String value) throws IllegalArgumentException {
958 fill(findColumn(column), value);
959 }
960
961 /** Fill String value in a column.
962 * @param column The column number.
963 * @param value The value to be filled in the current row.
964 * @throws IllegalArgumentException if value can't be filled. */
965 public void fill(int column, String value) throws IllegalArgumentException {
966 if (_readOnly) {
967 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
968 }
969 try {
970 _statement.setString(column+1, value);
971 }
972 catch (SQLException e) {
973 log.error(Util.report("Can't set column " + column + " to String value " + value, e), e);
974 throw new IllegalArgumentException("Couldn't column " + column + " to String value " + value, e);
975 }
976 _filled[column] = true;
977 }
978
979 /** Fill Object value in a column.
980 * @param column The column name.
981 * @param value The value to be filled in the current row.
982 * @throws IllegalArgumentException if value can't be filled. */
983 public void fill(String column, Object value) throws IllegalArgumentException {
984 fill(findColumn(column), value);
985 }
986
987 /** Fill Object value in a column.
988 * @param column The column number.
989 * @param value The value to be filled in the current row.
990 * @throws IllegalArgumentException if value can't be filled. */
991 public void fill(int column, Object value) throws IllegalArgumentException {
992 if (_readOnly) {
993 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
994 }
995 try {
996 _statement.setObject(column+1, value);
997 }
998 catch (SQLException e) {
999 log.error(Util.report("Can't set column " + column + " to Object value " + value, e), e);
1000 throw new IllegalArgumentException("Couldn't column " + column + " to Object value " + value, e);
1001 }
1002 _filled[column] = true;
1003 }
1004
1005 /** Fill float values into current row.
1006 * @param values The values to be filled in the current row.
1007 * @throws IllegalArgumentException if value can't be filled. */
1008 public void fill(float[] values) throws IllegalArgumentException {
1009 if (_readOnly) {
1010 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
1011 }
1012 for (int i = 0; i < columns(); i++) {
1013 try {
1014 _statement.setFloat(i+1, values[i]);
1015 }
1016 catch (SQLException e) {
1017 log.error(Util.report("Can't set column " + i + " to float value " + values[i], e), e);
1018 throw new IllegalArgumentException("Couldn't column " + i + " to float value " + values[i], e);
1019 }
1020 _filled[i] = true;
1021 }
1022 }
1023
1024 /** Fill double values into current row.
1025 * @param values The values to be filled in the current row.
1026 * @throws IllegalArgumentException if value can't be filled. */
1027 public void fill(double[] values) throws IllegalArgumentException {
1028 if (_readOnly) {
1029 throw new IllegalArgumentException("SQLTuple is readonly, can't be filled");
1030 }
1031 for (int i = 0; i < columns(); i++) {
1032 try {
1033 _statement.setDouble(i+1, values[i]);
1034 }
1035 catch (SQLException e) {
1036 log.error(Util.report("Can't set column " + i + " to double value " + values[i], e), e);
1037 throw new IllegalArgumentException("Couldn't column " + i + " to double value " + values[i], e);
1038 }
1039 _filled[i] = true;
1040 }
1041 }
1042
1043 /** Get the number of the current row.
1044 * @return The current row number. */
1045 public int row() {
1046 return getRow();
1047 }
1048
1049 /** Get the number of the current row.
1050 * @return The current row number. */
1051 public int getRow() {
1052 try {
1053 return _rs.getRow();
1054 }
1055 catch (SQLException e) {
1056 log.error(Util.report("Can't get row, returned 0", e), e);
1057 }
1058 return 0;
1059 }
1060
1061 /** Go to the row with specified number.
1062 * @param row The number of row to go to.
1063 * @throws IllegalArgumentException if can't go to specified row.*/
1064 public void setRow(int row) throws IllegalArgumentException {
1065 try {
1066 _rs.absolute(row);
1067 }
1068 catch (SQLException e) {
1069 log.error(Util.report("Can't set row to " + row, e), e);
1070 throw new IllegalArgumentException("Couldn't set row to " + row, e);
1071 }
1072 }
1073
1074 /** Start looping, positions in the first row. */
1075 public void start() {
1076 if (_names != _namesOrig) {
1077 _names = _namesOrig;
1078 _types = _typesOrig;
1079 _defaults = _defaultsOrig;
1080 _defaultObjects = _defaultObjectsOrig;
1081 }
1082 String[] args = {title()};
1083 _rs = query("start", args);
1084 }
1085
1086 /** <code>SQLTuple</code> extension: get subNTuple (subset of rows)
1087 * and positions in the first row. Use {@link IFilter}.
1088 * @param filter The IFilter to be used to select rows.
1089 * @throws SQLTupleException if can't get subNTuple.*/
1090 public void start(IFilter filter) throws SQLTupleException {
1091 String[] args = {filter.expression()};
1092 _rs = query("startFilter", args);
1093 }
1094
1095 /** <code>SQLTuple</code> extension: get subNTuple (subset of columns)
1096 * and positions in the first row. Use SQL command from {@link StmtSrc}.
1097 * @param stmtSrc The SQL Stmt String to be used to select rows.
1098 * @throws SQLTupleException if can't get subNTuple.*/
1099 public void start(String stmtSrc) throws SQLTupleException {
1100 String[] args = {};
1101 _rs = query(stmtSrc, args);
1102 try {
1103 ResultSetMetaData rsmd = _rs.getMetaData();
1104 int cols = rsmd.getColumnCount();
1105 _names = new String[cols];
1106 _types = new Class[cols];
1107 for (int i = 0; i < cols; i++) {
1108 _names[i] = rsmd.getColumnName(i+1);
1109 for (int j = 0; j < _namesOrig.length; j++) {
1110 if (_names[i].equals(_namesOrig[j])) {
1111 _types[i] = _typesOrig[j];
1112 break;
1113 }
1114 }
1115 }
1116 }
1117 catch (SQLException e) {
1118 throw new SQLTupleException("Can't start using Statement " + stmtSrc, e);
1119 }
1120 }
1121
1122 /** <code>SQLTuple</code> extension: get subNTuple (subset of rows and columns)
1123 * and positions in the first row. Use {@link IFilter} and
1124 * SQL command from {@link StmtSrc}.
1125 * @param filter The IFilter to be used to select rows.
1126 * @param stmtSrc The SQL Stmt String to be used to select rows.
1127 * @throws SQLTupleException if can't get subNTuple.*/
1128 public void start(IFilter filter,
1129 String stmtSrc) throws SQLTupleException {
1130 String[] args = {filter.expression()};
1131 _rs = query(stmtSrc, args);
1132 try {
1133 ResultSetMetaData rsmd = _rs.getMetaData();
1134 int cols = rsmd.getColumnCount();
1135 _names = new String[cols];
1136 _types = new Class[cols];
1137 for (int i = 0; i < cols; i++) {
1138 _names[i] = rsmd.getColumnName(i+1);
1139 for (int j = 0; j < _namesOrig.length; j++) {
1140 if (_names[i].equals(_namesOrig[j])) {
1141 _types[i] = _typesOrig[j];
1142 break;
1143 }
1144 }
1145 }
1146 }
1147 catch (SQLException e) {
1148 throw new SQLTupleException("Can't start using Statement " + stmtSrc, e);
1149 }
1150 }
1151
1152 /** <code>SQLTuple</code> extension: get subNTuple (subset of columns)
1153 * and positions in the first row.
1154 * @param columns The names of column to be extracted.
1155 * @throws SQLTupleException if can't get subNTuple.*/
1156 public void start(String[] columns) throws SQLTupleException {
1157 String[] args = new String[1];
1158 args[0] = "";
1159 for (int i = 0; i < columns.length; i++) {
1160 args[0] += columns[i];
1161 if (i < columns.length - 1) {
1162 args[0] += ",";
1163 }
1164 }
1165 _rs = query("getColumn", args);
1166 try {
1167 ResultSetMetaData rsmd = _rs.getMetaData();
1168 int cols = rsmd.getColumnCount();
1169 _names = new String[cols];
1170 _types = new Class[cols];
1171 for (int i = 0; i < cols; i++) {
1172 _names[i] = rsmd.getColumnName(i+1);
1173 for (int j = 0; j < _namesOrig.length; j++) {
1174 if (_names[i].equals(_namesOrig[j])) {
1175 _types[i] = _typesOrig[j];
1176 break;
1177 }
1178 }
1179 }
1180 }
1181 catch (SQLException e) {
1182 throw new SQLTupleException("Can't start using Statement getColumnFilter", e);
1183 }
1184 }
1185
1186 /** <code>SQLTuple</code> extension: get subNTuple (subset of rows and columns)
1187 * and positions in the first row. Uses {@link IFilter} and
1188 * SQL command from {@link StmtSrc}.
1189 * @param filter The IFilter to be used to select rows.
1190 * @param columns The names of column to be extracted.
1191 * @throws SQLTupleException if can't get subNTuple.*/
1192 public void start(IFilter filter, String[] columns) throws SQLTupleException {
1193 String[] args = new String[2];
1194 args[0] = "";
1195 for (int i = 0; i < columns.length; i++) {
1196 args[0] += columns[i];
1197 if (i < columns.length - 1) {
1198 args[0] += ",";
1199 }
1200 }
1201 args[1] = filter.expression();
1202 _rs = query("getColumnFilter", args);
1203 try {
1204 ResultSetMetaData rsmd = _rs.getMetaData();
1205 int cols = rsmd.getColumnCount();
1206 _names = new String[cols];
1207 _types = new Class[cols];
1208 for (int i = 0; i < cols; i++) {
1209 _names[i] = rsmd.getColumnName(i+1);
1210 for (int j = 0; j < _namesOrig.length; j++) {
1211 if (_names[i].equals(_namesOrig[j])) {
1212 _types[i] = _typesOrig[j];
1213 break;
1214 }
1215 }
1216 }
1217 }
1218 catch (SQLException e) {
1219 throw new SQLTupleException("Can't start using Statement getColumnFilter", e);
1220 }
1221 }
1222
1223 /** Skip rows.
1224 * @param rows The number of rows to skip. */
1225 public void skip(int rows) {
1226 try {
1227 _rs.relative(rows);
1228 }
1229 catch (SQLException e) {
1230 log.error(Util.report("Can't skip " + rows + " rows", e), e);
1231 throw new IllegalArgumentException("Couldn't skip " + rows + " rows", e);
1232 }
1233 }
1234
1235 /** Go into the next row.
1236 * @return true if success. */
1237 public boolean next() {
1238 try {
1239 if (_rs == null) {
1240 throw new SQLException("ResultSet not available");
1241 }
1242 return _rs.next();
1243 }
1244 catch (SQLException e) {
1245 log.error(Util.report("Can't go to next row", e), e);
1246 }
1247 return false;
1248 }
1249
1250 /** <code>SQLTuple</code> extension: return current Row Data.
1251 * @return The array of Strings representing the current row. */
1252 public String[] getRowData() {
1253 String[] values = new String[_names.length];
1254 try {
1255 for (int i = 0; i < values.length; i++) {
1256 values[i] = _rs.getString(i+1);
1257 }
1258 }
1259 catch (SQLException e) {
1260 log.error(Util.report("Can't get Row Data", e), e);
1261 }
1262 return values;
1263 }
1264
1265 /** Add the current row into NTuple and reset.
1266 * Not set columns are set to their default values. */
1267 public void addRow() {
1268 for (int i = 0; i < columns(); i++) {
1269 if (!_filled[i]) {
1270 log.debug("Value of column " + i + " not set, using default value: " + _types[i] + " " + _names[i] + " = " + _defaults[i]);
1271 fill(i, _defaultObjects[i]);
1272 }
1273 }
1274 try {
1275 if (_rows == -1) {
1276 rows();
1277 }
1278 _rows += updatePrepared(_statement);
1279 }
1280 catch (SQLTupleException e) {
1281 log.error(Util.report("Can't execute PreparedStatement", e), e);
1282 }
1283 finally {
1284 resetRow();
1285 }
1286 }
1287
1288 /** Prepare statement for adding row. */
1289 public void prepare(){
1290 StringBuffer values = new StringBuffer();
1291 for (int i = 0; i < _names.length; i++) {
1292 _filled[i] = false;
1293 values.append("?");
1294 if (i < _names.length - 1) {
1295 values.append(", ");
1296 }
1297 }
1298 String[] args = {values.toString()};
1299 try {
1300 _statement = _stmtSrc.prepare("addRow", args);
1301 }
1302 catch (SQLTupleException e) {
1303 log.warn("Can't prepare statement addRow");
1304 _readOnly = true;
1305 }
1306 }
1307
1308 /** Gets the name of the column number <code>param</code>.
1309 * @param param The number of column.
1310 * @return The name of the column. */
1311 public String columnName(int param) {
1312 return _names[param];
1313 }
1314
1315 /** Gets the number of the column name <code>name</code>.
1316 * @param name The number of column.
1317 * @return The number of the column.
1318 * @throws IllegalArgumentException if no column with that name exists. */
1319 public int columnNumber(String name) throws IllegalArgumentException {
1320 if (_names != null) {
1321 for (int i = 0; i < _names.length; i++) {
1322 if (_names[i].equals(name)) {
1323 return i;
1324 }
1325 }
1326 }
1327 throw new IllegalArgumentException("There is no column " + name);
1328 }
1329
1330 /** Get all column names.
1331 * @return The array of Strings with all column names. */
1332 public String[] columnNames() {
1333 return _names;
1334 }
1335
1336 /** Get the type of the column number <code>param</code>.
1337 * @param param The number of column.
1338 * @return The type of the column. */
1339 public Class columnType(int param) {
1340 return _types[param];
1341 }
1342
1343 /** Get all column types.
1344 * @return The array of Classes with all column types. */
1345 public Class[] columnTypes() {
1346 return _types;
1347 }
1348
1349 /** <code>SQLTuple</code> extension:
1350 * Get the default value of the column number <code>param</code>.
1351 * @param param The number of column.
1352 * @return The default value of the column. */
1353 public String columnDefault(int param) {
1354 return _defaults[param];
1355 }
1356
1357 /** Give the default as a String.
1358 * @param column The number of column.
1359 * @return The String representation of the default. */
1360 public String columnDefaultString(int column) {
1361 return _defaults[column];
1362 }
1363
1364 /** <code>SQLTuple</code> extension:
1365 * Get all column default values.
1366 * @return The array of Strings with all column default values. */
1367 public String[] columnDefaults() {
1368 return _defaults;
1369 }
1370
1371 /** Gets the number of columns.
1372 * @return The number of columns. */
1373 public int columns() {
1374 return _names.length;
1375 }
1376
1377 /** Reset the NTuple/table, close it. */
1378 public void reset() {
1379 try {
1380 _rs.close();
1381 }
1382 catch (SQLException e) {
1383 log.error(Util.report("Can't reset", e), e);
1384 }
1385 _rs = null;
1386 }
1387
1388 /** Reset the current row. */
1389 public void resetRow() throws IllegalArgumentException {
1390 try {
1391 _statement.clearParameters();
1392 for (int i = 0; i < columns(); i++) {
1393 _filled[i] = false;
1394 }
1395 }
1396 catch (SQLException e) {
1397 log.error(Util.report("Can't reset row", e), e);
1398 throw new IllegalArgumentException("Couldn't reset row", e);
1399 }
1400 }
1401
1402 /** Get the number of rows.
1403 * @return The number of rows. */
1404 public int rows() throws IllegalArgumentException {
1405 if (_rows == -1) {
1406 try {
1407 ResultSet rs = query("rows", null);
1408 rs.next();
1409 _rows = rs.getInt(1);
1410 rs.close();
1411 }
1412 catch (SQLException e) {
1413 log.error(Util.report("Can't get rows", e), e);
1414 throw new IllegalArgumentException("Couldn't get rows", e);
1415 }
1416 }
1417 return _rows;
1418 }
1419
1420 /** Get column.
1421 * @param index The column number.
1422 * @return The requested {@link TupleColumn} */
1423 public IBaseTupleColumn column(int index) {
1424 return new SQLTupleColumn(this, index);
1425 }
1426
1427 /** Get column.
1428 * @param name The column name.
1429 * @return The requested {@link TupleColumn} */
1430 public FTupleColumn columnByName(String name) {
1431 return new SQLTupleColumn(this, findColumn(name));
1432 }
1433
1434 /** Give nested {@link ITuple}. It is not supported.
1435 * @param index The column's index of the Folder.
1436 * @return The nested {@link ITuple}.
1437 * @throws UnsupportedOperationException always, because opereation is not supported. */
1438 public ITuple findTuple(int index) throws UnsupportedOperationException {
1439 throw new UnsupportedOperationException("Operation not supported in SQLTuple");
1440 }
1441
1442 /** Get {@link FTupleCursor}.
1443 * @return The requested {@link FTupleCursor} */
1444 public FTupleCursor cursor() throws IllegalStateException {
1445 return new SQLTupleCursor(this);
1446 }
1447
1448 /** Get {@link Value} of column at {@link FTupleCursor}.
1449 * @param column The column, value of which is requested.
1450 * @param value The {@link Value} to be filled. */
1451 public void columnValue(int column, Value value) {
1452 Class cl = columnType(column);
1453 if (cl == Byte.TYPE) value.set(getByte(column));
1454 else if (cl == Boolean.TYPE) value.set(getBoolean(column));
1455 else if (cl == Character.TYPE) value.set(getChar(column));
1456 else if (cl == Short.TYPE) value.set(getShort(column));
1457 else if (cl == Integer.TYPE) value.set(getInt(column));
1458 else if (cl == Long.TYPE) value.set(getLong(column));
1459 else if (cl == Float.TYPE) value.set(getFloat(column));
1460 else if (cl == Double.TYPE) value.set(getDouble(column));
1461 else if (cl == String.class) value.set(getString(column));
1462 else value.set(getString(column));
1463 }
1464
1465 /** Get {@link Value} of column at {@link FTupleCursor}.
1466 * @param column The column, value of which is requested.
1467 * @param cursor The {@link FTupleCursor} pointing to requested row.
1468 * @param value The {@link Value} to be filled. */
1469 public void columnValue(int column, FTupleCursor cursor, Value value) {
1470 columnValue(column, value);
1471 }
1472
1473 /** Get double value from the {@link ResultSet}. If direct <code>rs.getDouble(...)</code>
1474 * fails, <code>rs.getString(...)</code> and conversion to String is tried.
1475 * @param rs The {@link ResultSet} to be used. The current row will be inspected.
1476 * @param i The column to be used.
1477 * @return The found double value.
1478 * @throws IllegalArgumentException if double value can't be extracted, even via String value. */
1479 private double getDouble(ResultSet rs, int i) throws IllegalArgumentException {
1480 // Try as double
1481 try {
1482 return rs.getDouble(i);
1483 }
1484 // Double failed
1485 catch (SQLException e) {
1486 // Try as String, convert to double
1487 try {
1488 String s = rs.getString(i);
1489 log.debug("Can't make projection, can't convert " + s + " to double, going via String: " + e.toString());
1490 return new Double(s);
1491 }
1492 // String failed
1493 catch (SQLException ee) {
1494 log.error(Util.report("Can't make projection", ee), ee);
1495 throw new IllegalArgumentException("Couldn't make projection", ee);
1496 }
1497 }
1498 }
1499
1500 public void project(ICloud1D cloud,
1501 IEvaluator evaluatorX) throws IllegalArgumentException {
1502 String[] args = {evaluatorX.expression()};
1503 ResultSet rs = query("projectX", args);
1504 try {
1505 while (rs.next()) {
1506 cloud.fill(getDouble(rs, 1));
1507 }
1508 }
1509 catch (Exception e) {
1510 log.error(Util.report("Can't make projection", e), e);
1511 throw new IllegalArgumentException("Couldn't make projection", e);
1512 }
1513 }
1514
1515 public void project(ICloud1D cloud,
1516 IEvaluator evaluatorX,
1517 IEvaluator weight) throws IllegalArgumentException {
1518 String[] args = {evaluatorX.expression(),
1519 weight.expression()};
1520 ResultSet rs = query("projectXW", args);
1521 try {
1522 while (rs.next()) {
1523 cloud.fill(getDouble(rs, 1), getDouble(rs, 2));
1524 }
1525 }
1526 catch (SQLException e) {
1527 log.error(Util.report("Can't make projection", e), e);
1528 throw new IllegalArgumentException("Couldn't make projection", e);
1529 }
1530 }
1531
1532 public void project(ICloud1D cloud,
1533 IEvaluator evaluatorX,
1534 IFilter filter) throws IllegalArgumentException {
1535 String[] args = {evaluatorX.expression(),
1536 filter.expression()};
1537 ResultSet rs = query("projectXF", args);
1538 try {
1539 while (rs.next()) {
1540 cloud.fill(getDouble(rs, 1));
1541 }
1542 }
1543 catch (SQLException e) {
1544 log.error(Util.report("Can't make projection", e), e);
1545 throw new IllegalArgumentException("Couldn't make projection", e);
1546 }
1547 }
1548
1549 public void project(ICloud1D cloud,
1550 IEvaluator evaluatorX,
1551 IFilter filter,
1552 IEvaluator weight) throws IllegalArgumentException {
1553 String[] args = {evaluatorX.expression(),
1554 weight.expression(),
1555 filter.expression()};
1556 ResultSet rs = query("projectXFW", args);
1557 try {
1558 while (rs.next()) {
1559 cloud.fill(getDouble(rs, 1), getDouble(rs, 2));
1560 }
1561 }
1562 catch (SQLException e) {
1563 log.error(Util.report("Can't make projection", e), e);
1564 throw new IllegalArgumentException("Couldn't make projection", e);
1565 }
1566 }
1567
1568 public void project(ICloud2D cloud,
1569 IEvaluator evaluatorX,
1570 IEvaluator evaluatorY) throws IllegalArgumentException {
1571 String[] args = {evaluatorX.expression(),
1572 evaluatorY.expression()};
1573 ResultSet rs = query("projectXY", args);
1574 try {
1575 while (rs.next()) {
1576 cloud.fill(getDouble(rs, 1), getDouble(rs, 2));
1577 }
1578 }
1579 catch (SQLException e) {
1580 log.error(Util.report("Can't make projection", e), e);
1581 throw new IllegalArgumentException("Couldn't make projection", e);
1582 }
1583 }
1584
1585 public void project(ICloud2D cloud,
1586 IEvaluator evaluatorX,
1587 IEvaluator evaluatorY,
1588 IEvaluator weight) throws IllegalArgumentException {
1589 String[] args = {evaluatorX.expression(),
1590 evaluatorY.expression(),
1591 weight.expression()};
1592 ResultSet rs = query("projectXYW", args);
1593 try {
1594 while (rs.next()) {
1595 cloud.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1596 }
1597 }
1598 catch (SQLException e) {
1599 log.error(Util.report("Can't make projection", e), e);
1600 throw new IllegalArgumentException("Couldn't make projection", e);
1601 }
1602 }
1603
1604 public void project(ICloud2D cloud,
1605 IEvaluator evaluatorX,
1606 IEvaluator evaluatorY,
1607 IFilter filter) throws IllegalArgumentException {
1608 String[] args = {evaluatorX.expression(),
1609 evaluatorY.expression(),
1610 filter.expression()};
1611 ResultSet rs = query("projectXYF", args);
1612 try {
1613 while (rs.next()) {
1614 cloud.fill(getDouble(rs, 1), getDouble(rs, 2));
1615 }
1616 }
1617 catch (SQLException e) {
1618 log.error(Util.report("Can't make projection", e), e);
1619 throw new IllegalArgumentException("Couldn't make projection", e);
1620 }
1621 }
1622
1623 public void project(ICloud2D cloud,
1624 IEvaluator evaluatorX,
1625 IEvaluator evaluatorY,
1626 IFilter filter,
1627 IEvaluator weight) throws IllegalArgumentException {
1628 String[] args = {evaluatorX.expression(),
1629 evaluatorY.expression(),
1630 weight.expression(),
1631 filter.expression()};
1632 ResultSet rs = query("projectXYFW", args);
1633 try {
1634 while (rs.next()) {
1635 cloud.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1636 }
1637 }
1638 catch (SQLException e) {
1639 log.error(Util.report("Can't make projection", e), e);
1640 throw new IllegalArgumentException("Couldn't make projection", e);
1641 }
1642 }
1643
1644 public void project(ICloud3D cloud,
1645 IEvaluator evaluatorX,
1646 IEvaluator evaluatorY,
1647 IEvaluator evaluatorZ) throws IllegalArgumentException {
1648 String[] args = {evaluatorX.expression(),
1649 evaluatorY.expression(),
1650 evaluatorZ.expression()};
1651 ResultSet rs = query("projectXYZ", args);
1652 try {
1653 while (rs.next()) {
1654 cloud.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1655 }
1656 }
1657 catch (SQLException e) {
1658 log.error(Util.report("Can't make projection", e), e);
1659 throw new IllegalArgumentException("Couldn't make projection", e);
1660 }
1661 }
1662
1663 public void project(ICloud3D cloud,
1664 IEvaluator evaluatorX,
1665 IEvaluator evaluatorY,
1666 IEvaluator evaluatorZ,
1667 IEvaluator weight) throws IllegalArgumentException {
1668 String[] args = {evaluatorX.expression(),
1669 evaluatorY.expression(),
1670 evaluatorZ.expression(),
1671 weight.expression()};
1672 ResultSet rs = query("projectXYZW", args);
1673 try {
1674 while (rs.next()) {
1675 cloud.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
1676 }
1677 }
1678 catch (SQLException e) {
1679 log.error(Util.report("Can't make projection", e), e);
1680 throw new IllegalArgumentException("Couldn't make projection", e);
1681 }
1682 }
1683
1684 public void project(ICloud3D cloud,
1685 IEvaluator evaluatorX,
1686 IEvaluator evaluatorY,
1687 IEvaluator evaluatorZ,
1688 IFilter filter) throws IllegalArgumentException {
1689 String[] args = {evaluatorX.expression(),
1690 evaluatorY.expression(),
1691 evaluatorZ.expression(),
1692 filter.expression()};
1693 ResultSet rs = query("projectXYZF", args);
1694 try {
1695 while (rs.next()) {
1696 cloud.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
1697 }
1698 }
1699 catch (SQLException e) {
1700 log.error(Util.report("Can't make projection", e), e);
1701 throw new IllegalArgumentException("Couldn't make projection", e);
1702 }
1703 }
1704
1705 public void project(ICloud3D cloud,
1706 IEvaluator evaluatorX,
1707 IEvaluator evaluatorY,
1708 IEvaluator evaluatorZ,
1709 IFilter filter,
1710 IEvaluator weight) throws IllegalArgumentException {
1711 String[] args = {evaluatorX.expression(),
1712 evaluatorY.expression(),
1713 evaluatorZ.expression(),
1714 weight.expression(),
1715 filter.expression()};
1716 ResultSet rs = query("projectXYZFW", args);
1717 try {
1718 while (rs.next()) {
1719 cloud.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
1720 }
1721 }
1722 catch (SQLException e) {
1723 log.error(Util.report("Can't make projection", e), e);
1724 throw new IllegalArgumentException("Couldn't make projection", e);
1725 }
1726 }
1727
1728 public void project(IHistogram1D histogram,
1729 IEvaluator evaluatorX) throws IllegalArgumentException {
1730 String[] args = {evaluatorX.expression()};
1731 ResultSet rs = query("projectX", args);
1732 try {
1733 while (rs.next()) {
1734 histogram.fill(getDouble(rs, 1));
1735 }
1736 }
1737 catch (SQLException e) {
1738 log.error(Util.report("Can't make projection", e), e);
1739 throw new IllegalArgumentException("Couldn't make projection", e);
1740 }
1741 }
1742
1743 public void project(IHistogram1D histogram,
1744 IEvaluator evaluatorX,
1745 IEvaluator weight) throws IllegalArgumentException {
1746 String[] args = {evaluatorX.expression(),
1747 weight.expression()};
1748 ResultSet rs = query("projectXW", args);
1749 try {
1750 while (rs.next()) {
1751 histogram.fill(getDouble(rs, 1), getDouble(rs, 2));
1752 }
1753 }
1754 catch (SQLException e) {
1755 log.error(Util.report("Can't make projection", e), e);
1756 throw new IllegalArgumentException("Couldn't make projection", e);
1757 }
1758 }
1759
1760 public void project(IHistogram1D histogram,
1761 IEvaluator evaluatorX,
1762 IFilter filter) throws IllegalArgumentException {
1763 String[] args = {evaluatorX.expression(),
1764 filter.expression()};
1765 ResultSet rs = query("projectXF", args);
1766 try {
1767 while (rs.next()) {
1768 histogram.fill(getDouble(rs, 1));
1769 }
1770 }
1771 catch (SQLException e) {
1772 log.error(Util.report("Can't make projection", e), e);
1773 throw new IllegalArgumentException("Couldn't make projection", e);
1774 }
1775 }
1776
1777 public void project(IHistogram1D histogram,
1778 IEvaluator evaluatorX,
1779 IFilter filter,
1780 IEvaluator weight) throws IllegalArgumentException {
1781 String[] args = {evaluatorX.expression(),
1782 weight.expression(),
1783 filter.expression()};
1784 ResultSet rs = query("projectXFW", args);
1785 try {
1786 while (rs.next()) {
1787 histogram.fill(getDouble(rs, 1), getDouble(rs, 2));
1788 }
1789 }
1790 catch (SQLException e) {
1791 log.error(Util.report("Can't make projection", e), e);
1792 throw new IllegalArgumentException("Couldn't make projection", e);
1793 }
1794 }
1795
1796 public void project(IHistogram2D histogram,
1797 IEvaluator evaluatorX,
1798 IEvaluator evaluatorY) throws IllegalArgumentException {
1799 String[] args = {evaluatorX.expression(),
1800 evaluatorY.expression()};
1801 ResultSet rs = query("projectXY", args);
1802 try {
1803 while (rs.next()) {
1804 histogram.fill(getDouble(rs, 1), getDouble(rs, 2));
1805 }
1806 }
1807 catch (SQLException e) {
1808 log.error(Util.report("Can't make projection", e), e);
1809 throw new IllegalArgumentException("Couldn't make projection", e);
1810 }
1811 }
1812
1813 public void project(IHistogram2D histogram,
1814 IEvaluator evaluatorX,
1815 IEvaluator evaluatorY,
1816 IEvaluator weight) throws IllegalArgumentException {
1817 String[] args = {evaluatorX.expression(),
1818 evaluatorY.expression(),
1819 weight.expression()};
1820 ResultSet rs = query("projectXYW", args);
1821 try {
1822 while (rs.next()) {
1823 histogram.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1824 }
1825 }
1826 catch (SQLException e) {
1827 log.error(Util.report("Can't make projection", e), e);
1828 throw new IllegalArgumentException("Couldn't make projection", e);
1829 }
1830 }
1831
1832 public void project(IHistogram2D histogram,
1833 IEvaluator evaluatorX,
1834 IEvaluator evaluatorY,
1835 IFilter filter) throws IllegalArgumentException {
1836 String[] args = {evaluatorX.expression(),
1837 evaluatorY.expression(),
1838 filter.expression()};
1839 ResultSet rs = query("projectXYF", args);
1840 try {
1841 while (rs.next()) {
1842 histogram.fill(getDouble(rs, 1), getDouble(rs, 2));
1843 }
1844 }
1845 catch (SQLException e) {
1846 log.error(Util.report("Can't make projection", e), e);
1847 throw new IllegalArgumentException("Couldn't make projection", e);
1848 }
1849 }
1850
1851 public void project(IHistogram2D histogram,
1852 IEvaluator evaluatorX,
1853 IEvaluator evaluatorY,
1854 IFilter filter,
1855 IEvaluator weight) throws IllegalArgumentException {
1856 String[] args = {evaluatorX.expression(),
1857 evaluatorY.expression(),
1858 weight.expression(),
1859 filter.expression()};
1860 ResultSet rs = query("projectXYFW", args);
1861 try {
1862 while (rs.next()) {
1863 histogram.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1864 }
1865 }
1866 catch (SQLException e) {
1867 log.error(Util.report("Can't make projection", e), e);
1868 throw new IllegalArgumentException("Couldn't make projection", e);
1869 }
1870 }
1871
1872 public void project(IHistogram3D histogram,
1873 IEvaluator evaluatorX,
1874 IEvaluator evaluatorY,
1875 IEvaluator evaluatorZ) throws IllegalArgumentException {
1876 String[] args = {evaluatorX.expression(),
1877 evaluatorY.expression(),
1878 evaluatorZ.expression()};
1879 ResultSet rs = query("projectXYZ", args);
1880 try {
1881 while (rs.next()) {
1882 histogram.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1883 }
1884 }
1885 catch (SQLException e) {
1886 log.error(Util.report("Can't make projection", e), e);
1887 throw new IllegalArgumentException("Couldn't make projection", e);
1888 }
1889 }
1890
1891 public void project(IHistogram3D histogram,
1892 IEvaluator evaluatorX,
1893 IEvaluator evaluatorY,
1894 IEvaluator evaluatorZ,
1895 IEvaluator weight) throws IllegalArgumentException {
1896 String[] args = {evaluatorX.expression(),
1897 evaluatorY.expression(),
1898 evaluatorZ.expression(),
1899 weight.expression()};
1900 ResultSet rs = query("projectXYZW", args);
1901 try {
1902 while (rs.next()) {
1903 histogram.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
1904 }
1905 }
1906 catch (SQLException e) {
1907 log.error(Util.report("Can't make projection", e), e);
1908 throw new IllegalArgumentException("Couldn't make projection", e);
1909 }
1910 }
1911
1912 public void project(IHistogram3D histogram,
1913 IEvaluator evaluatorX,
1914 IEvaluator evaluatorY,
1915 IEvaluator evaluatorZ,
1916 IFilter filter) throws IllegalArgumentException {
1917 String[] args = {evaluatorX.expression(),
1918 evaluatorY.expression(),
1919 evaluatorZ.expression(),
1920 filter.expression()};
1921 ResultSet rs = query("projectXYZF", args);
1922 try {
1923 while (rs.next()) {
1924 histogram.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
1925 }
1926 }
1927 catch (SQLException e) {
1928 log.error(Util.report("Can't make projection", e), e);
1929 throw new IllegalArgumentException("Couldn't make projection", e);
1930 }
1931 }
1932
1933 public void project(IHistogram3D histogram,
1934 IEvaluator evaluatorX,
1935 IEvaluator evaluatorY,
1936 IEvaluator evaluatorZ,
1937 IFilter filter,
1938 IEvaluator weight) throws IllegalArgumentException {
1939 String[] args = {evaluatorX.expression(),
1940 evaluatorY.expression(),
1941 evaluatorZ.expression(),
1942 weight.expression(),
1943 filter.expression()};
1944 ResultSet rs = query("projectXYZFW", args);
1945 try {
1946 while (rs.next()) {
1947 histogram.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
1948 }
1949 }
1950 catch (SQLException e) {
1951 log.error(Util.report("Can't make projection", e), e);
1952 throw new IllegalArgumentException("Couldn't make projection", e);
1953 }
1954 }
1955
1956 public void project(IProfile1D profile,
1957 IEvaluator evaluatorX,
1958 IEvaluator evaluatorY) throws IllegalArgumentException {
1959 String[] args = {evaluatorX.expression(),
1960 evaluatorY.expression()};
1961 ResultSet rs = query("projectXY", args);
1962 try {
1963 while (rs.next()) {
1964 profile.fill(getDouble(rs, 1), getDouble(rs, 2));
1965 }
1966 }
1967 catch (SQLException e) {
1968 log.error(Util.report("Can't make projection", e), e);
1969 throw new IllegalArgumentException("Couldn't make projection", e);
1970 }
1971 }
1972
1973 public void project(IProfile1D profile,
1974 IEvaluator evaluatorX,
1975 IEvaluator evaluatorY,
1976 IEvaluator weight) throws IllegalArgumentException {
1977 String[] args = {evaluatorX.expression(),
1978 evaluatorY.expression(),
1979 weight.expression()};
1980 ResultSet rs = query("projectXYW", args);
1981 try {
1982 while (rs.next()) {
1983 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
1984 }
1985 }
1986 catch (SQLException e) {
1987 log.error(Util.report("Can't make projection", e), e);
1988 throw new IllegalArgumentException("Couldn't make projection", e);
1989 }
1990 }
1991
1992 public void project(IProfile1D profile,
1993 IEvaluator evaluatorX,
1994 IEvaluator evaluatorY,
1995 IFilter filter) throws IllegalArgumentException {
1996 String[] args = {evaluatorX.expression(),
1997 evaluatorY.expression(),
1998 filter.expression()};
1999 ResultSet rs = query("projectXYF", args);
2000 try {
2001 while (rs.next()) {
2002 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
2003 }
2004 }
2005 catch (SQLException e) {
2006 log.error(Util.report("Can't make projection", e), e);
2007 throw new IllegalArgumentException("Couldn't make projection", e);
2008 }
2009 }
2010
2011 public void project(IProfile1D profile,
2012 IEvaluator evaluatorX,
2013 IEvaluator evaluatorY,
2014 IFilter filter,
2015 IEvaluator weight) throws IllegalArgumentException {
2016 String[] args = {evaluatorX.expression(),
2017 evaluatorY.expression(),
2018 weight.expression(),
2019 filter.expression()};
2020 ResultSet rs = query("projectXYFW", args);
2021 try {
2022 while (rs.next()) {
2023 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
2024 }
2025 }
2026 catch (SQLException e) {
2027 log.error(Util.report("Can't make projection", e), e);
2028 throw new IllegalArgumentException("Couldn't make projection", e);
2029 }
2030 }
2031
2032 public void project(IProfile2D profile,
2033 IEvaluator evaluatorX,
2034 IEvaluator evaluatorY,
2035 IEvaluator evaluatorZ) throws IllegalArgumentException {
2036 String[] args = {evaluatorX.expression(),
2037 evaluatorY.expression(),
2038 evaluatorZ.expression()};
2039 ResultSet rs = query("projectXYZ", args);
2040 try {
2041 while (rs.next()) {
2042 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3));
2043 }
2044 }
2045 catch (SQLException e) {
2046 log.error(Util.report("Can't make projection", e), e);
2047 throw new IllegalArgumentException("Couldn't make projection", e);
2048 }
2049 }
2050
2051 public void project(IProfile2D profile,
2052 IEvaluator evaluatorX,
2053 IEvaluator evaluatorY,
2054 IEvaluator evaluatorZ,
2055 IEvaluator weight) throws IllegalArgumentException {
2056 String[] args = {evaluatorX.expression(),
2057 evaluatorY.expression(),
2058 evaluatorZ.expression(),
2059 weight.expression()};
2060 ResultSet rs = query("projectXYZW", args);
2061 try {
2062 while (rs.next()) {
2063 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
2064 }
2065 }
2066 catch (SQLException e) {
2067 log.error(Util.report("Can't make projection", e), e);
2068 throw new IllegalArgumentException("Couldn't make projection", e);
2069 }
2070 }
2071
2072 public void project(IProfile2D profile,
2073 IEvaluator evaluatorX,
2074 IEvaluator evaluatorY,
2075 IEvaluator evaluatorZ,
2076 IFilter filter) throws IllegalArgumentException {
2077 String[] args = {evaluatorX.expression(),
2078 evaluatorY.expression(),
2079 evaluatorZ.expression(),
2080 filter.expression()};
2081 ResultSet rs = query("projectXYZF", args);
2082 try {
2083 while (rs.next()) {
2084 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
2085 }
2086 }
2087 catch (SQLException e) {
2088 log.error(Util.report("Can't make projection", e), e);
2089 throw new IllegalArgumentException("Couldn't make projection", e);
2090 }
2091 }
2092
2093 public void project(IProfile2D profile,
2094 IEvaluator evaluatorX,
2095 IEvaluator evaluatorY,
2096 IEvaluator evaluatorZ,
2097 IFilter filter,
2098 IEvaluator weight) throws IllegalArgumentException {
2099 String[] args = {evaluatorX.expression(),
2100 evaluatorY.expression(),
2101 evaluatorZ.expression(),
2102 weight.expression(),
2103 filter.expression()};
2104 ResultSet rs = query("projectXYZFW", args);
2105 try {
2106 while (rs.next()) {
2107 profile.fill(getDouble(rs, 1), getDouble(rs, 2), getDouble(rs, 3), getDouble(rs, 4));
2108 }
2109 }
2110 catch (SQLException e) {
2111 log.error(Util.report("Can't make projection", e), e);
2112 throw new IllegalArgumentException("Couldn't make projection", e);
2113 }
2114 }
2115
2116 /** <code>SQLTuple</code> extension: get the whole column as an array
2117 * of Strings.
2118 * @param cName The name of the column.
2119 * @return The {@link Collection} containing the whole column as Strings. */
2120 public Collection<String> getColumn(String cName) {
2121 return getColumn(cName, String.class);
2122 }
2123
2124 /** <code>SQLTuple</code> extension: get the whole column as an array
2125 * of Objects of the specified Class (which has to have a String constructor).
2126 * @param cName The name of the column.
2127 * @param cl The Class (with String constructor) to be used to create Objects for {@link Collection}.
2128 * @return The {@link Collection} containing the whole column as Objects of specified Class. */
2129 public <T> Collection<T> getColumn(String cName,
2130 Class<T> cl) {
2131 return getColumn(cName, cl, null);
2132 }
2133
2134 /** <code>SQLTuple</code> extension: get the filtered column as an array
2135 * of Strings.
2136 * @param cName The name of the column.
2137 * @param filter The {@link IFilter} to be used to select rows.
2138 * @return The [@link Collection} containing the whole column as Strings. */
2139 public Collection<String> getColumn(String cName,
2140 IFilter filter) {
2141 return getColumn(cName, String.class, filter);
2142 }
2143
2144 /** <code>SQLTuple</code> extension: get the filtered column as an array
2145 * of Objects of the specified Class (it has to have a String constructor).
2146 * @param cName The name of the column.
2147 * @param cl The Class (with String constructor) to be used to create Objects for {@link Collection}.
2148 * @param filter The {@link IFilter} to be used to select rows.
2149 * @return The {@link Collection} containing the whole column as Objects of specified Class. */
2150 public <T> Collection<T> getColumn(String cName,
2151 Class<T> cl,
2152 IFilter filter) {
2153 Collection<T> values = new ArrayList<T>();
2154 Class[] parameters = {String.class};
2155 Constructor<T> constructor = null;
2156 try {
2157 constructor = cl.getConstructor(parameters);
2158 }
2159 catch(NoSuchMethodException e) {
2160 log.error(Util.report("Can't find constructor " + cl + "(" + cName + "), return empty Collection", e), e);
2161 return values;
2162 }
2163 Object args[];
2164 T obj = null;
2165 ResultSet rs = null;
2166 if (filter == null) {
2167 String[] args0 = {cName};
2168 rs = query("getColumn", args0);
2169 }
2170 else {
2171 String[] args0 = {cName, filter.expression()};
2172 rs = query("getColumnFilter", args0);
2173 }
2174 try {
2175 while (rs.next()) {
2176 args = new Object[1];
2177 args[0] = rs.getString(1);
2178 try {
2179 obj = constructor.newInstance(args);
2180 values.add((T)obj);
2181 }
2182 catch(InstantiationException e) {
2183 log.error(Util.report("Can't construct " + cl + " from " + args[0] + ", return empty Collection", e), e);
2184 }
2185 catch(IllegalAccessException e) {
2186 log.error(Util.report("Can't construct " + cl + " from " + args[0] + ", return empty Collection", e), e);
2187 }
2188 catch(InvocationTargetException e) {
2189 log.error(Util.report("Can't construct " + cl + " from " + args[0] + ", return empty Collection", e), e);
2190 }
2191 }
2192 }
2193 catch (SQLException e) {
2194 log.error(Util.report("Can't get column " + cName + " with filter " + filter.expression() + " as Collection<String>, return empty Collection", e), e);
2195 }
2196 return values;
2197 }
2198
2199 /** Register options.
2200 * @param options The options string to be registered.
2201 * @throws SQLTupleException if Accessor can't be created. */
2202 public void setOptions(String options) throws SQLTupleException {
2203 _accessor = Accessor.getAccessor(options);
2204 }
2205
2206 /** Get attached {@link Accessor}.
2207 * @return The associated Accessor. */
2208 public Accessor accessor() {
2209 return _accessor;
2210 }
2211
2212 /** Perform update operation via {@link StmtSrc}.
2213 * @param statementString The SQL statement to be used.
2214 * @param args The arguments to be filled into the SQL statement in place of X*.
2215 * @return The number of added rows.
2216 * @throws IllegalArgumentException if the update can't be performed. */
2217 private int update(String statementString,
2218 String[] args) throws IllegalArgumentException {
2219 try {
2220 return _stmtSrc.update(statementString, args);
2221 }
2222 catch(SQLTupleException e) {
2223 log.error(Util.report("Can't perform update " + statementString, e), e);
2224 throw new IllegalArgumentException("Couldn't perform update " + statementString, e);
2225 }
2226 }
2227
2228 /** Perform update operation via {@link StmtSrc} using {@link PreparedStatement}.
2229 * @param statement The SQL {@link PreparedStatement} to be used.
2230 * @return The number of added rows.
2231 * @throws SQLTupleException if the update can't be performed. */
2232 private int updatePrepared(PreparedStatement statement) throws SQLTupleException {
2233 try {
2234 return _stmtSrc.updatePrepared(statement);
2235 }
2236 catch(SQLTupleException e) {
2237 log.error(Util.report("Can't perform update using Prepared Statement " + statement, e), e);
2238 throw new IllegalArgumentException("Couldn't perform update using Prepared Statement " + statement, e);
2239 }
2240 }
2241
2242 /** Perform query operation via {@link StmtSrc}.
2243 * @param statementString The SQL statement to be used.
2244 * @param args The arguments to be filled into the SQL statement in place of X*.
2245 * @return The results of the SQL command.
2246 * @throws IllegalArgumentException if the update can't be performed. */
2247 private ResultSet query(String statementString,
2248 String[] args) throws IllegalArgumentException {
2249 try {
2250 ResultSet rs = _stmtSrc.query(statementString, args);
2251 if (!_accessor.forwardOnly()) {
2252 rs.last();
2253 _rows = rs.getRow();
2254 rs.beforeFirst();
2255 }
2256 return rs;
2257 }
2258 catch(Exception e) {
2259 log.error(Util.report("Can't perform query " + statementString, e), e);
2260 throw new IllegalArgumentException("Couldn't perform query " + statementString, e);
2261 }
2262 }
2263
2264 /** Give attached {@link StmtSrc}.
2265 * @return The attached {@link StmtSrc}. */
2266 public StmtSrc stmtSrc() {
2267 return _stmtSrc;
2268 }
2269
2270 /** Attached {@link StmtSrc}.
2271 * @param url The {@link StmtSrc} to be attached. */
2272 public void setStmtSrc(String url) {
2273 String src = _accessor.src();
2274 _accessor.setSrc(url);
2275 try {
2276 _stmtSrc = new StmtSrc(_accessor, title());
2277 }
2278 catch (SQLTupleException e) {
2279 log.error(Util.report("Can't (re)set StmtSrc to " + url, e), e);
2280 _accessor.setSrc(src);
2281 }
2282 }
2283
2284 /** Create Object from String value.
2285 * @param value The value as {@link String}.
2286 * @param type The type of the requested Object.
2287 * @return The Object of the requested type with the requested value. */
2288 private Object type2Object(String value, Class type) {
2289 Object valueObject;
2290 if (type == Integer.TYPE ) valueObject = ((value == null) ? (int )0 : Integer.parseInt( value));
2291 else if (type == Short.TYPE ) valueObject = ((value == null) ? (short )0 : Short.parseShort( value));
2292 else if (type == Long.TYPE ) valueObject = ((value == null) ? (long )0 : Long.parseLong( value));
2293 else if (type == Float.TYPE ) valueObject = ((value == null) ? (float )0 : Float.parseFloat( value));
2294 else if (type == Double.TYPE ) valueObject = ((value == null) ? (double)0 : Double.parseDouble(value));
2295 else if (type == Boolean.TYPE ) valueObject = ((value == null) ? false : Boolean.valueOf( value).booleanValue());
2296 else if (type == Byte.TYPE ) valueObject = ((value == null) ? (byte )0 : Byte.parseByte( value));
2297 else if (type == Character.TYPE) valueObject = ((value == null) ? (char )0 : value.charAt(0));
2298 else valueObject = ((value == null) ? "" : value);
2299 return valueObject;
2300 }
2301
2302 private Accessor _accessor;
2303
2304 private StmtSrc _stmtSrc;
2305
2306 private PreparedStatement _statement;
2307
2308 private ResultSet _rs;
2309
2310 private String[] _names;
2311
2312 private Class[] _types;
2313
2314 private String[] _defaults;
2315
2316 private Object[] _defaultObjects;
2317
2318 private String[] _namesOrig;
2319
2320 private Class[] _typesOrig;
2321
2322 private String[] _defaultsOrig;
2323
2324 private Object[] _defaultObjectsOrig;
2325
2326 private boolean[] _filled;
2327
2328 private int _rows;
2329
2330 private boolean _readOnly = false;
2331
2332 /** Logging . */
2333 private static Logger log = Logger.getLogger(SQLTuple.class);
2334
2335 }