1 | /* |
---|
2 | * This program is free software; you can redistribute it and/or modify |
---|
3 | * it under the terms of the GNU General Public License as published by |
---|
4 | * the Free Software Foundation; either version 2 of the License, or |
---|
5 | * (at your option) any later version. |
---|
6 | * |
---|
7 | * This program is distributed in the hope that it will be useful, |
---|
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | * GNU General Public License for more details. |
---|
11 | * |
---|
12 | * You should have received a copy of the GNU General Public License |
---|
13 | * along with this program; if not, write to the Free Software |
---|
14 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
15 | */ |
---|
16 | |
---|
17 | /* |
---|
18 | * InstanceQuery.java |
---|
19 | * Copyright (C) 1999 University of Waikato, Hamilton, New Zealand |
---|
20 | * |
---|
21 | */ |
---|
22 | |
---|
23 | package weka.experiment; |
---|
24 | |
---|
25 | import weka.core.Attribute; |
---|
26 | import weka.core.FastVector; |
---|
27 | import weka.core.Instance; |
---|
28 | import weka.core.DenseInstance; |
---|
29 | import weka.core.Instances; |
---|
30 | import weka.core.Option; |
---|
31 | import weka.core.OptionHandler; |
---|
32 | import weka.core.RevisionUtils; |
---|
33 | import weka.core.SparseInstance; |
---|
34 | import weka.core.Utils; |
---|
35 | |
---|
36 | import java.sql.ResultSet; |
---|
37 | import java.sql.ResultSetMetaData; |
---|
38 | import java.sql.Time; |
---|
39 | import java.util.Date; |
---|
40 | import java.util.Enumeration; |
---|
41 | import java.util.Hashtable; |
---|
42 | import java.util.Vector; |
---|
43 | |
---|
44 | /** |
---|
45 | * Convert the results of a database query into instances. The jdbc |
---|
46 | * driver and database to be used default to "jdbc.idbDriver" and |
---|
47 | * "jdbc:idb=experiments.prp". These may be changed by creating |
---|
48 | * a java properties file called DatabaseUtils.props in user.home or |
---|
49 | * the current directory. eg:<p> |
---|
50 | * |
---|
51 | * <code><pre> |
---|
52 | * jdbcDriver=jdbc.idbDriver |
---|
53 | * jdbcURL=jdbc:idb=experiments.prp |
---|
54 | * </pre></code><p> |
---|
55 | * |
---|
56 | * Command line use just outputs the instances to System.out. <p/> |
---|
57 | * |
---|
58 | <!-- options-start --> |
---|
59 | * Valid options are: <p/> |
---|
60 | * |
---|
61 | * <pre> -Q <query> |
---|
62 | * SQL query to execute.</pre> |
---|
63 | * |
---|
64 | * <pre> -S |
---|
65 | * Return sparse rather than normal instances.</pre> |
---|
66 | * |
---|
67 | * <pre> -U <username> |
---|
68 | * The username to use for connecting.</pre> |
---|
69 | * |
---|
70 | * <pre> -P <password> |
---|
71 | * The password to use for connecting.</pre> |
---|
72 | * |
---|
73 | * <pre> -D |
---|
74 | * Enables debug output.</pre> |
---|
75 | * |
---|
76 | <!-- options-end --> |
---|
77 | * |
---|
78 | * @author Len Trigg (trigg@cs.waikato.ac.nz) |
---|
79 | * @version $Revision: 5987 $ |
---|
80 | */ |
---|
81 | public class InstanceQuery |
---|
82 | extends DatabaseUtils |
---|
83 | implements OptionHandler { |
---|
84 | |
---|
85 | /** for serialization */ |
---|
86 | static final long serialVersionUID = 718158370917782584L; |
---|
87 | |
---|
88 | /** Determines whether sparse data is created */ |
---|
89 | boolean m_CreateSparseData = false; |
---|
90 | |
---|
91 | /** Query to execute */ |
---|
92 | String m_Query = "SELECT * from ?"; |
---|
93 | |
---|
94 | /** |
---|
95 | * Sets up the database drivers |
---|
96 | * |
---|
97 | * @throws Exception if an error occurs |
---|
98 | */ |
---|
99 | public InstanceQuery() throws Exception { |
---|
100 | |
---|
101 | super(); |
---|
102 | } |
---|
103 | |
---|
104 | /** |
---|
105 | * Returns an enumeration describing the available options <p> |
---|
106 | * |
---|
107 | * @return an enumeration of all options |
---|
108 | */ |
---|
109 | public Enumeration listOptions () { |
---|
110 | Vector result = new Vector(); |
---|
111 | |
---|
112 | result.addElement( |
---|
113 | new Option("\tSQL query to execute.", |
---|
114 | "Q",1,"-Q <query>")); |
---|
115 | |
---|
116 | result.addElement( |
---|
117 | new Option("\tReturn sparse rather than normal instances.", |
---|
118 | "S", 0, "-S")); |
---|
119 | |
---|
120 | result.addElement( |
---|
121 | new Option("\tThe username to use for connecting.", |
---|
122 | "U", 1, "-U <username>")); |
---|
123 | |
---|
124 | result.addElement( |
---|
125 | new Option("\tThe password to use for connecting.", |
---|
126 | "P", 1, "-P <password>")); |
---|
127 | |
---|
128 | result.addElement( |
---|
129 | new Option("\tEnables debug output.", |
---|
130 | "D", 0, "-D")); |
---|
131 | |
---|
132 | return result.elements(); |
---|
133 | } |
---|
134 | |
---|
135 | /** |
---|
136 | * Parses a given list of options. |
---|
137 | * |
---|
138 | <!-- options-start --> |
---|
139 | * Valid options are: <p/> |
---|
140 | * |
---|
141 | * <pre> -Q <query> |
---|
142 | * SQL query to execute.</pre> |
---|
143 | * |
---|
144 | * <pre> -S |
---|
145 | * Return sparse rather than normal instances.</pre> |
---|
146 | * |
---|
147 | * <pre> -U <username> |
---|
148 | * The username to use for connecting.</pre> |
---|
149 | * |
---|
150 | * <pre> -P <password> |
---|
151 | * The password to use for connecting.</pre> |
---|
152 | * |
---|
153 | * <pre> -D |
---|
154 | * Enables debug output.</pre> |
---|
155 | * |
---|
156 | <!-- options-end --> |
---|
157 | * |
---|
158 | * @param options the list of options as an array of strings |
---|
159 | * @throws Exception if an option is not supported |
---|
160 | */ |
---|
161 | public void setOptions (String[] options) |
---|
162 | throws Exception { |
---|
163 | |
---|
164 | String tmpStr; |
---|
165 | |
---|
166 | setSparseData(Utils.getFlag('S',options)); |
---|
167 | |
---|
168 | tmpStr = Utils.getOption('Q',options); |
---|
169 | if (tmpStr.length() != 0) |
---|
170 | setQuery(tmpStr); |
---|
171 | |
---|
172 | tmpStr = Utils.getOption('U',options); |
---|
173 | if (tmpStr.length() != 0) |
---|
174 | setUsername(tmpStr); |
---|
175 | |
---|
176 | tmpStr = Utils.getOption('P',options); |
---|
177 | if (tmpStr.length() != 0) |
---|
178 | setPassword(tmpStr); |
---|
179 | |
---|
180 | setDebug(Utils.getFlag('D',options)); |
---|
181 | } |
---|
182 | |
---|
183 | /** |
---|
184 | * Returns the tip text for this property |
---|
185 | * @return tip text for this property suitable for |
---|
186 | * displaying in the explorer/experimenter gui |
---|
187 | */ |
---|
188 | public String queryTipText() { |
---|
189 | return "The SQL query to execute against the database."; |
---|
190 | } |
---|
191 | |
---|
192 | /** |
---|
193 | * Set the query to execute against the database |
---|
194 | * @param q the query to execute |
---|
195 | */ |
---|
196 | public void setQuery(String q) { |
---|
197 | m_Query = q; |
---|
198 | } |
---|
199 | |
---|
200 | /** |
---|
201 | * Get the query to execute against the database |
---|
202 | * @return the query |
---|
203 | */ |
---|
204 | public String getQuery() { |
---|
205 | return m_Query; |
---|
206 | } |
---|
207 | |
---|
208 | /** |
---|
209 | * Returns the tip text for this property |
---|
210 | * @return tip text for this property suitable for |
---|
211 | * displaying in the explorer/experimenter gui |
---|
212 | */ |
---|
213 | public String sparseDataTipText() { |
---|
214 | return "Encode data as sparse instances."; |
---|
215 | } |
---|
216 | |
---|
217 | /** |
---|
218 | * Sets whether data should be encoded as sparse instances |
---|
219 | * @param s true if data should be encoded as a set of sparse instances |
---|
220 | */ |
---|
221 | public void setSparseData(boolean s) { |
---|
222 | m_CreateSparseData = s; |
---|
223 | } |
---|
224 | |
---|
225 | /** |
---|
226 | * Gets whether data is to be returned as a set of sparse instances |
---|
227 | * @return true if data is to be encoded as sparse instances |
---|
228 | */ |
---|
229 | public boolean getSparseData() { |
---|
230 | return m_CreateSparseData; |
---|
231 | } |
---|
232 | |
---|
233 | /** |
---|
234 | * Gets the current settings of InstanceQuery |
---|
235 | * |
---|
236 | * @return an array of strings suitable for passing to setOptions() |
---|
237 | */ |
---|
238 | public String[] getOptions () { |
---|
239 | |
---|
240 | Vector options = new Vector(); |
---|
241 | |
---|
242 | options.add("-Q"); |
---|
243 | options.add(getQuery()); |
---|
244 | |
---|
245 | if (getSparseData()) |
---|
246 | options.add("-S"); |
---|
247 | |
---|
248 | if (!getUsername().equals("")) { |
---|
249 | options.add("-U"); |
---|
250 | options.add(getUsername()); |
---|
251 | } |
---|
252 | |
---|
253 | if (!getPassword().equals("")) { |
---|
254 | options.add("-P"); |
---|
255 | options.add(getPassword()); |
---|
256 | } |
---|
257 | |
---|
258 | if (getDebug()) |
---|
259 | options.add("-D"); |
---|
260 | |
---|
261 | return (String[]) options.toArray(new String[options.size()]); |
---|
262 | } |
---|
263 | |
---|
264 | /** |
---|
265 | * Makes a database query using the query set through the -Q option |
---|
266 | * to convert a table into a set of instances |
---|
267 | * |
---|
268 | * @return the instances contained in the result of the query |
---|
269 | * @throws Exception if an error occurs |
---|
270 | */ |
---|
271 | public Instances retrieveInstances() throws Exception { |
---|
272 | return retrieveInstances(m_Query); |
---|
273 | } |
---|
274 | |
---|
275 | /** |
---|
276 | * Makes a database query to convert a table into a set of instances |
---|
277 | * |
---|
278 | * @param query the query to convert to instances |
---|
279 | * @return the instances contained in the result of the query, NULL if the |
---|
280 | * SQL query doesn't return a ResultSet, e.g., DELETE/INSERT/UPDATE |
---|
281 | * @throws Exception if an error occurs |
---|
282 | */ |
---|
283 | public Instances retrieveInstances(String query) throws Exception { |
---|
284 | |
---|
285 | if (m_Debug) |
---|
286 | System.err.println("Executing query: " + query); |
---|
287 | connectToDatabase(); |
---|
288 | if (execute(query) == false) { |
---|
289 | if (m_PreparedStatement.getUpdateCount() == -1) { |
---|
290 | throw new Exception("Query didn't produce results"); |
---|
291 | } |
---|
292 | else { |
---|
293 | if (m_Debug) |
---|
294 | System.err.println(m_PreparedStatement.getUpdateCount() |
---|
295 | + " rows affected."); |
---|
296 | close(); |
---|
297 | return null; |
---|
298 | } |
---|
299 | } |
---|
300 | ResultSet rs = getResultSet(); |
---|
301 | if (m_Debug) |
---|
302 | System.err.println("Getting metadata..."); |
---|
303 | ResultSetMetaData md = rs.getMetaData(); |
---|
304 | if (m_Debug) |
---|
305 | System.err.println("Completed getting metadata..."); |
---|
306 | |
---|
307 | |
---|
308 | // Determine structure of the instances |
---|
309 | int numAttributes = md.getColumnCount(); |
---|
310 | int [] attributeTypes = new int [numAttributes]; |
---|
311 | Hashtable [] nominalIndexes = new Hashtable [numAttributes]; |
---|
312 | FastVector [] nominalStrings = new FastVector [numAttributes]; |
---|
313 | for (int i = 1; i <= numAttributes; i++) { |
---|
314 | /* switch (md.getColumnType(i)) { |
---|
315 | case Types.CHAR: |
---|
316 | case Types.VARCHAR: |
---|
317 | case Types.LONGVARCHAR: |
---|
318 | case Types.BINARY: |
---|
319 | case Types.VARBINARY: |
---|
320 | case Types.LONGVARBINARY:*/ |
---|
321 | |
---|
322 | switch (translateDBColumnType(md.getColumnTypeName(i))) { |
---|
323 | |
---|
324 | case STRING : |
---|
325 | //System.err.println("String --> nominal"); |
---|
326 | attributeTypes[i - 1] = Attribute.NOMINAL; |
---|
327 | nominalIndexes[i - 1] = new Hashtable(); |
---|
328 | nominalStrings[i - 1] = new FastVector(); |
---|
329 | break; |
---|
330 | case TEXT: |
---|
331 | //System.err.println("Text --> string"); |
---|
332 | attributeTypes[i - 1] = Attribute.STRING; |
---|
333 | nominalIndexes[i - 1] = new Hashtable(); |
---|
334 | nominalStrings[i - 1] = new FastVector(); |
---|
335 | break; |
---|
336 | case BOOL: |
---|
337 | //System.err.println("boolean --> nominal"); |
---|
338 | attributeTypes[i - 1] = Attribute.NOMINAL; |
---|
339 | nominalIndexes[i - 1] = new Hashtable(); |
---|
340 | nominalIndexes[i - 1].put("false", new Double(0)); |
---|
341 | nominalIndexes[i - 1].put("true", new Double(1)); |
---|
342 | nominalStrings[i - 1] = new FastVector(); |
---|
343 | nominalStrings[i - 1].addElement("false"); |
---|
344 | nominalStrings[i - 1].addElement("true"); |
---|
345 | break; |
---|
346 | case DOUBLE: |
---|
347 | //System.err.println("BigDecimal --> numeric"); |
---|
348 | attributeTypes[i - 1] = Attribute.NUMERIC; |
---|
349 | break; |
---|
350 | case BYTE: |
---|
351 | //System.err.println("byte --> numeric"); |
---|
352 | attributeTypes[i - 1] = Attribute.NUMERIC; |
---|
353 | break; |
---|
354 | case SHORT: |
---|
355 | //System.err.println("short --> numeric"); |
---|
356 | attributeTypes[i - 1] = Attribute.NUMERIC; |
---|
357 | break; |
---|
358 | case INTEGER: |
---|
359 | //System.err.println("int --> numeric"); |
---|
360 | attributeTypes[i - 1] = Attribute.NUMERIC; |
---|
361 | break; |
---|
362 | case LONG: |
---|
363 | //System.err.println("long --> numeric"); |
---|
364 | attributeTypes[i - 1] = Attribute.NUMERIC; |
---|
365 | break; |
---|
366 | case FLOAT: |
---|
367 | //System.err.println("float --> numeric"); |
---|
368 | attributeTypes[i - 1] = Attribute.NUMERIC; |
---|
369 | break; |
---|
370 | case DATE: |
---|
371 | attributeTypes[i - 1] = Attribute.DATE; |
---|
372 | break; |
---|
373 | case TIME: |
---|
374 | attributeTypes[i - 1] = Attribute.DATE; |
---|
375 | break; |
---|
376 | default: |
---|
377 | //System.err.println("Unknown column type"); |
---|
378 | attributeTypes[i - 1] = Attribute.STRING; |
---|
379 | } |
---|
380 | } |
---|
381 | |
---|
382 | // For sqlite |
---|
383 | // cache column names because the last while(rs.next()) { iteration for |
---|
384 | // the tuples below will close the md object: |
---|
385 | Vector<String> columnNames = new Vector<String>(); |
---|
386 | for (int i = 0; i < numAttributes; i++) { |
---|
387 | columnNames.add(md.getColumnName(i + 1)); |
---|
388 | } |
---|
389 | |
---|
390 | // Step through the tuples |
---|
391 | if (m_Debug) |
---|
392 | System.err.println("Creating instances..."); |
---|
393 | FastVector instances = new FastVector(); |
---|
394 | int rowCount = 0; |
---|
395 | while(rs.next()) { |
---|
396 | if (rowCount % 100 == 0) { |
---|
397 | if (m_Debug) { |
---|
398 | System.err.print("read " + rowCount + " instances \r"); |
---|
399 | System.err.flush(); |
---|
400 | } |
---|
401 | } |
---|
402 | double[] vals = new double[numAttributes]; |
---|
403 | for(int i = 1; i <= numAttributes; i++) { |
---|
404 | /*switch (md.getColumnType(i)) { |
---|
405 | case Types.CHAR: |
---|
406 | case Types.VARCHAR: |
---|
407 | case Types.LONGVARCHAR: |
---|
408 | case Types.BINARY: |
---|
409 | case Types.VARBINARY: |
---|
410 | case Types.LONGVARBINARY:*/ |
---|
411 | switch (translateDBColumnType(md.getColumnTypeName(i))) { |
---|
412 | case STRING : |
---|
413 | String str = rs.getString(i); |
---|
414 | |
---|
415 | if (rs.wasNull()) { |
---|
416 | vals[i - 1] = Utils.missingValue(); |
---|
417 | } else { |
---|
418 | Double index = (Double)nominalIndexes[i - 1].get(str); |
---|
419 | if (index == null) { |
---|
420 | index = new Double(nominalStrings[i - 1].size()); |
---|
421 | nominalIndexes[i - 1].put(str, index); |
---|
422 | nominalStrings[i - 1].addElement(str); |
---|
423 | } |
---|
424 | vals[i - 1] = index.doubleValue(); |
---|
425 | } |
---|
426 | break; |
---|
427 | case TEXT: |
---|
428 | String txt = rs.getString(i); |
---|
429 | |
---|
430 | if (rs.wasNull()) { |
---|
431 | vals[i - 1] = Utils.missingValue(); |
---|
432 | } else { |
---|
433 | Double index = (Double)nominalIndexes[i - 1].get(txt); |
---|
434 | if (index == null) { |
---|
435 | index = new Double(nominalStrings[i - 1].size()); |
---|
436 | nominalIndexes[i - 1].put(txt, index); |
---|
437 | nominalStrings[i - 1].addElement(txt); |
---|
438 | } |
---|
439 | vals[i - 1] = index.doubleValue(); |
---|
440 | } |
---|
441 | break; |
---|
442 | case BOOL: |
---|
443 | boolean boo = rs.getBoolean(i); |
---|
444 | if (rs.wasNull()) { |
---|
445 | vals[i - 1] = Utils.missingValue(); |
---|
446 | } else { |
---|
447 | vals[i - 1] = (boo ? 1.0 : 0.0); |
---|
448 | } |
---|
449 | break; |
---|
450 | case DOUBLE: |
---|
451 | // BigDecimal bd = rs.getBigDecimal(i, 4); |
---|
452 | double dd = rs.getDouble(i); |
---|
453 | // Use the column precision instead of 4? |
---|
454 | if (rs.wasNull()) { |
---|
455 | vals[i - 1] = Utils.missingValue(); |
---|
456 | } else { |
---|
457 | // newInst.setValue(i - 1, bd.doubleValue()); |
---|
458 | vals[i - 1] = dd; |
---|
459 | } |
---|
460 | break; |
---|
461 | case BYTE: |
---|
462 | byte by = rs.getByte(i); |
---|
463 | if (rs.wasNull()) { |
---|
464 | vals[i - 1] = Utils.missingValue(); |
---|
465 | } else { |
---|
466 | vals[i - 1] = (double)by; |
---|
467 | } |
---|
468 | break; |
---|
469 | case SHORT: |
---|
470 | short sh = rs.getShort(i); |
---|
471 | if (rs.wasNull()) { |
---|
472 | vals[i - 1] = Utils.missingValue(); |
---|
473 | } else { |
---|
474 | vals[i - 1] = (double)sh; |
---|
475 | } |
---|
476 | break; |
---|
477 | case INTEGER: |
---|
478 | int in = rs.getInt(i); |
---|
479 | if (rs.wasNull()) { |
---|
480 | vals[i - 1] = Utils.missingValue(); |
---|
481 | } else { |
---|
482 | vals[i - 1] = (double)in; |
---|
483 | } |
---|
484 | break; |
---|
485 | case LONG: |
---|
486 | long lo = rs.getLong(i); |
---|
487 | if (rs.wasNull()) { |
---|
488 | vals[i - 1] = Utils.missingValue(); |
---|
489 | } else { |
---|
490 | vals[i - 1] = (double)lo; |
---|
491 | } |
---|
492 | break; |
---|
493 | case FLOAT: |
---|
494 | float fl = rs.getFloat(i); |
---|
495 | if (rs.wasNull()) { |
---|
496 | vals[i - 1] = Utils.missingValue(); |
---|
497 | } else { |
---|
498 | vals[i - 1] = (double)fl; |
---|
499 | } |
---|
500 | break; |
---|
501 | case DATE: |
---|
502 | Date date = rs.getDate(i); |
---|
503 | if (rs.wasNull()) { |
---|
504 | vals[i - 1] = Utils.missingValue(); |
---|
505 | } else { |
---|
506 | // TODO: Do a value check here. |
---|
507 | vals[i - 1] = (double)date.getTime(); |
---|
508 | } |
---|
509 | break; |
---|
510 | case TIME: |
---|
511 | Time time = rs.getTime(i); |
---|
512 | if (rs.wasNull()) { |
---|
513 | vals[i - 1] = Utils.missingValue(); |
---|
514 | } else { |
---|
515 | // TODO: Do a value check here. |
---|
516 | vals[i - 1] = (double) time.getTime(); |
---|
517 | } |
---|
518 | break; |
---|
519 | default: |
---|
520 | vals[i - 1] = Utils.missingValue(); |
---|
521 | } |
---|
522 | } |
---|
523 | Instance newInst; |
---|
524 | if (m_CreateSparseData) { |
---|
525 | newInst = new SparseInstance(1.0, vals); |
---|
526 | } else { |
---|
527 | newInst = new DenseInstance(1.0, vals); |
---|
528 | } |
---|
529 | instances.addElement(newInst); |
---|
530 | rowCount++; |
---|
531 | } |
---|
532 | //disconnectFromDatabase(); (perhaps other queries might be made) |
---|
533 | |
---|
534 | // Create the header and add the instances to the dataset |
---|
535 | if (m_Debug) |
---|
536 | System.err.println("Creating header..."); |
---|
537 | FastVector attribInfo = new FastVector(); |
---|
538 | for (int i = 0; i < numAttributes; i++) { |
---|
539 | /* Fix for databases that uppercase column names */ |
---|
540 | // String attribName = attributeCaseFix(md.getColumnName(i + 1)); |
---|
541 | String attribName = attributeCaseFix(columnNames.get(i)); |
---|
542 | switch (attributeTypes[i]) { |
---|
543 | case Attribute.NOMINAL: |
---|
544 | attribInfo.addElement(new Attribute(attribName, nominalStrings[i])); |
---|
545 | break; |
---|
546 | case Attribute.NUMERIC: |
---|
547 | attribInfo.addElement(new Attribute(attribName)); |
---|
548 | break; |
---|
549 | case Attribute.STRING: |
---|
550 | Attribute att = new Attribute(attribName, (FastVector) null); |
---|
551 | attribInfo.addElement(att); |
---|
552 | for (int n = 0; n < nominalStrings[i].size(); n++) { |
---|
553 | att.addStringValue((String) nominalStrings[i].elementAt(n)); |
---|
554 | } |
---|
555 | break; |
---|
556 | case Attribute.DATE: |
---|
557 | attribInfo.addElement(new Attribute(attribName, (String)null)); |
---|
558 | break; |
---|
559 | default: |
---|
560 | throw new Exception("Unknown attribute type"); |
---|
561 | } |
---|
562 | } |
---|
563 | Instances result = new Instances("QueryResult", attribInfo, |
---|
564 | instances.size()); |
---|
565 | for (int i = 0; i < instances.size(); i++) { |
---|
566 | result.add((Instance)instances.elementAt(i)); |
---|
567 | } |
---|
568 | close(rs); |
---|
569 | |
---|
570 | return result; |
---|
571 | } |
---|
572 | |
---|
573 | /** |
---|
574 | * Test the class from the command line. The instance |
---|
575 | * query should be specified with -Q sql_query |
---|
576 | * |
---|
577 | * @param args contains options for the instance query |
---|
578 | */ |
---|
579 | public static void main(String args[]) { |
---|
580 | |
---|
581 | try { |
---|
582 | InstanceQuery iq = new InstanceQuery(); |
---|
583 | String query = Utils.getOption('Q', args); |
---|
584 | if (query.length() == 0) { |
---|
585 | iq.setQuery("select * from Experiment_index"); |
---|
586 | } else { |
---|
587 | iq.setQuery(query); |
---|
588 | } |
---|
589 | iq.setOptions(args); |
---|
590 | try { |
---|
591 | Utils.checkForRemainingOptions(args); |
---|
592 | } catch (Exception e) { |
---|
593 | System.err.println("Options for weka.experiment.InstanceQuery:\n"); |
---|
594 | Enumeration en = iq.listOptions(); |
---|
595 | while (en.hasMoreElements()) { |
---|
596 | Option o = (Option)en.nextElement(); |
---|
597 | System.err.println(o.synopsis()+"\n"+o.description()); |
---|
598 | } |
---|
599 | System.exit(1); |
---|
600 | } |
---|
601 | |
---|
602 | Instances aha = iq.retrieveInstances(); |
---|
603 | iq.disconnectFromDatabase(); |
---|
604 | // query returned no result -> exit |
---|
605 | if (aha == null) |
---|
606 | return; |
---|
607 | // The dataset may be large, so to make things easier we'll |
---|
608 | // output an instance at a time (rather than having to convert |
---|
609 | // the entire dataset to one large string) |
---|
610 | System.out.println(new Instances(aha, 0)); |
---|
611 | for (int i = 0; i < aha.numInstances(); i++) { |
---|
612 | System.out.println(aha.instance(i)); |
---|
613 | } |
---|
614 | } catch(Exception e) { |
---|
615 | e.printStackTrace(); |
---|
616 | System.err.println(e.getMessage()); |
---|
617 | } |
---|
618 | } |
---|
619 | |
---|
620 | /** |
---|
621 | * Returns the revision string. |
---|
622 | * |
---|
623 | * @return the revision |
---|
624 | */ |
---|
625 | public String getRevision() { |
---|
626 | return RevisionUtils.extract("$Revision: 5987 $"); |
---|
627 | } |
---|
628 | } |
---|