Source Code Cross Referenced for Fetch.java in  » Testing » Marathon » com » ziclix » python » sql » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » Marathon » com.ziclix.python.sql 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Jython Database Specification API 2.0
003:         *
004:         * $Id: Fetch.java 2542 2005-06-20 17:12:15Z fwierzbicki $
005:         *
006:         * Copyright (c) 2001 brian zimmer <bzimmer@ziclix.com>
007:         *
008:         */
009:        package com.ziclix.python.sql;
010:
011:        import org.python.core.Py;
012:        import org.python.core.PyException;
013:        import org.python.core.PyInteger;
014:        import org.python.core.PyList;
015:        import org.python.core.PyObject;
016:        import org.python.core.PyTuple;
017:        import org.python.core.__builtin__;
018:
019:        import java.sql.CallableStatement;
020:        import java.sql.DatabaseMetaData;
021:        import java.sql.ResultSet;
022:        import java.sql.ResultSetMetaData;
023:        import java.sql.SQLException;
024:        import java.sql.SQLWarning;
025:        import java.sql.Types;
026:        import java.util.ArrayList;
027:        import java.util.LinkedList;
028:        import java.util.List;
029:        import java.util.Set;
030:
031:        /**
032:         * <p>The responsibility of a Fetch instance is to manage the iteration of a
033:         * ResultSet.  Two different alogorithms are available: static or dynamic.</p>
034:         * <p/>
035:         * <p><b>Static</b> The static variety iterates the entire set immediately,
036:         * creating the necessary Jython objects and storing them.  It is able to
037:         * immediately close the ResultSet so a call to close() is essentially a no-op
038:         * from a database resource perspective (it does clear the results list however).
039:         * This approach also allows for the correct rowcount to be determined since
040:         * the entire result set has been iterated.</p>
041:         * <p/>
042:         * <p><b>Dynamic</b> The dynamic variety iterates the result set only as requested.
043:         * This holds a bit truer to the intent of the API as the fetch*() methods actually
044:         * fetch when instructed.  This is especially useful for managing exeedingly large
045:         * results, but is unable to determine the rowcount without having worked through
046:         * the entire result set.  The other disadvantage is the ResultSet remains open
047:         * throughout the entire iteration.  So the tradeoff is in open database resources
048:         * versus JVM resources since the application can keep constant space if it doesn't
049:         * require the entire result set be presented as one.</p>
050:         *
051:         * @author brian zimmer
052:         * @version $Revision: 2542 $
053:         */
054:        abstract public class Fetch {
055:
056:            /**
057:             * The total number of rows in the result set.
058:             * <p/>
059:             * Note: since JDBC provides no means to get this information without iterating
060:             * the entire result set, only those fetches which build the result statically
061:             * will have an accurate row count.
062:             */
063:            protected int rowcount;
064:
065:            /**
066:             * The current row of the cursor (-1 if off either end).
067:             */
068:            protected int rownumber;
069:
070:            /**
071:             * Field cursor
072:             */
073:            private DataHandler datahandler;
074:
075:            /**
076:             * Field description
077:             */
078:            protected PyObject description;
079:
080:            /**
081:             * A list of warning listeners.
082:             */
083:            private List listeners;
084:
085:            /**
086:             * Constructor Fetch
087:             *
088:             * @param datahandler
089:             */
090:            protected Fetch(DataHandler datahandler) {
091:
092:                this .rowcount = -1;
093:                this .rownumber = -1;
094:                this .description = Py.None;
095:                this .datahandler = datahandler;
096:                this .listeners = new ArrayList(3);
097:            }
098:
099:            /**
100:             * Method newFetch
101:             *
102:             * @param datahandler
103:             * @param dynamic
104:             * @return Fetch
105:             */
106:            public static Fetch newFetch(DataHandler datahandler,
107:                    boolean dynamic) {
108:
109:                if (dynamic) {
110:                    return new DynamicFetch(datahandler);
111:                } else {
112:                    return new StaticFetch(datahandler);
113:                }
114:            }
115:
116:            /**
117:             * The number of rows in the current result set.
118:             */
119:            public int getRowCount() {
120:                return this .rowcount;
121:            }
122:
123:            /**
124:             * The description of each column, in order, for the data in the result
125:             * set.
126:             */
127:            public PyObject getDescription() {
128:                return this .description;
129:            }
130:
131:            /**
132:             * Create the results after a successful execution and manages the result set.
133:             *
134:             * @param resultSet
135:             */
136:            abstract public void add(ResultSet resultSet);
137:
138:            /**
139:             * Create the results after a successful execution and manages the result set.
140:             * Optionally takes a set of JDBC-indexed columns to automatically set to None
141:             * primarily to support getTypeInfo() which sets a column type of a number but
142:             * doesn't use the value so a driver is free to put anything it wants there.
143:             *
144:             * @param resultSet
145:             * @param skipCols  JDBC-indexed set of columns to be skipped
146:             */
147:            abstract public void add(ResultSet resultSet, Set skipCols);
148:
149:            /**
150:             * Method add
151:             *
152:             * @param callableStatement
153:             * @param procedure
154:             * @param params
155:             */
156:            abstract public void add(CallableStatement callableStatement,
157:                    Procedure procedure, PyObject params);
158:
159:            /**
160:             * Fetch the next row of a query result set, returning a single sequence,
161:             * or None when no more data is available.
162:             * <p/>
163:             * An Error (or subclass) exception is raised if the previous call to
164:             * executeXXX() did not produce any result set or no call was issued yet.
165:             *
166:             * @return a single sequence from the result set, or None when no more data is available
167:             */
168:            public PyObject fetchone() {
169:
170:                PyObject sequence = fetchmany(1);
171:
172:                if (sequence.__len__() == 1) {
173:                    return sequence.__getitem__(0);
174:                } else {
175:                    return Py.None;
176:                }
177:            }
178:
179:            /**
180:             * Fetch all (remaining) rows of a query result, returning them as a sequence
181:             * of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute
182:             * can affect the performance of this operation.
183:             * <p/>
184:             * An Error (or subclass) exception is raised if the previous call to executeXXX()
185:             * did not produce any result set or no call was issued yet.
186:             *
187:             * @return a sequence of sequences from the result set, or None when no more data is available
188:             */
189:            public abstract PyObject fetchall();
190:
191:            /**
192:             * Fetch the next set of rows of a query result, returning a sequence of
193:             * sequences (e.g. a list of tuples). An empty sequence is returned when
194:             * no more rows are available.
195:             * <p/>
196:             * The number of rows to fetch per call is specified by the parameter. If
197:             * it is not given, the cursor's arraysize determines the number of rows
198:             * to be fetched. The method should try to fetch as many rows as indicated
199:             * by the size parameter. If this is not possible due to the specified number
200:             * of rows not being available, fewer rows may be returned.
201:             * <p/>
202:             * An Error (or subclass) exception is raised if the previous call to executeXXX()
203:             * did not produce any result set or no call was issued yet.
204:             * <p/>
205:             * Note there are performance considerations involved with the size parameter.
206:             * For optimal performance, it is usually best to use the arraysize attribute.
207:             * If the size parameter is used, then it is best for it to retain the same value
208:             * from one fetchmany() call to the next.
209:             *
210:             * @return a sequence of sequences from the result set, or None when no more data is available
211:             */
212:            public abstract PyObject fetchmany(int size);
213:
214:            /**
215:             * Move the result pointer to the next set if available.
216:             *
217:             * @return true if more sets exist, else None
218:             */
219:            public abstract PyObject nextset();
220:
221:            /**
222:             * Scroll the cursor in the result set to a new position according
223:             * to mode.
224:             * <p/>
225:             * If mode is 'relative' (default), value is taken as offset to
226:             * the current position in the result set, if set to 'absolute',
227:             * value states an absolute target position.
228:             * <p/>
229:             * An IndexError should be raised in case a scroll operation would
230:             * leave the result set. In this case, the cursor position is left
231:             * undefined (ideal would be to not move the cursor at all).
232:             * <p/>
233:             * Note: This method should use native scrollable cursors, if
234:             * available, or revert to an emulation for forward-only
235:             * scrollable cursors. The method may raise NotSupportedErrors to
236:             * signal that a specific operation is not supported by the
237:             * database (e.g. backward scrolling).
238:             *
239:             * @param value
240:             * @param mode
241:             */
242:            public abstract void scroll(int value, String mode);
243:
244:            /**
245:             * Cleanup any resources.
246:             */
247:            public void close() throws SQLException {
248:                this .listeners.clear();
249:            }
250:
251:            /**
252:             * Builds a tuple containing the meta-information about each column.
253:             * <p/>
254:             * (name, type_code, display_size, internal_size, precision, scale, null_ok)
255:             * <p/>
256:             * precision and scale are only available for numeric types
257:             */
258:            protected PyObject createDescription(ResultSetMetaData meta)
259:                    throws SQLException {
260:
261:                PyObject metadata = new PyList();
262:
263:                for (int i = 1; i <= meta.getColumnCount(); i++) {
264:                    PyObject[] a = new PyObject[7];
265:
266:                    a[0] = Py.newString(meta.getColumnName(i));
267:                    a[1] = Py.newInteger(meta.getColumnType(i));
268:                    a[2] = Py.newInteger(meta.getColumnDisplaySize(i));
269:                    a[3] = Py.None;
270:
271:                    switch (meta.getColumnType(i)) {
272:
273:                    case Types.BIGINT:
274:                    case Types.BIT:
275:                    case Types.DECIMAL:
276:                    case Types.DOUBLE:
277:                    case Types.FLOAT:
278:                    case Types.INTEGER:
279:                    case Types.SMALLINT:
280:                        a[4] = Py.newInteger(meta.getPrecision(i));
281:                        a[5] = Py.newInteger(meta.getScale(i));
282:                        break;
283:
284:                    default:
285:                        a[4] = Py.None;
286:                        a[5] = Py.None;
287:                        break;
288:                    }
289:
290:                    a[6] = Py.newInteger(meta.isNullable(i));
291:
292:                    ((PyList) metadata).append(new PyTuple(a));
293:                }
294:
295:                return metadata;
296:            }
297:
298:            /**
299:             * Builds a tuple containing the meta-information about each column.
300:             * <p/>
301:             * (name, type_code, display_size, internal_size, precision, scale, null_ok)
302:             * <p/>
303:             * precision and scale are only available for numeric types
304:             */
305:            protected PyObject createDescription(Procedure procedure)
306:                    throws SQLException {
307:
308:                PyObject metadata = new PyList();
309:
310:                for (int i = 0, len = procedure.columns.__len__(); i < len; i++) {
311:                    PyObject column = procedure.columns.__getitem__(i);
312:                    int colType = ((PyInteger) column.__getitem__(
313:                            Procedure.COLUMN_TYPE).__int__()).getValue();
314:
315:                    switch (colType) {
316:
317:                    case DatabaseMetaData.procedureColumnReturn:
318:                        PyObject[] a = new PyObject[7];
319:
320:                        a[0] = column.__getitem__(Procedure.NAME);
321:                        a[1] = column.__getitem__(Procedure.DATA_TYPE);
322:                        a[2] = Py.newInteger(-1);
323:                        a[3] = column.__getitem__(Procedure.LENGTH);
324:
325:                        switch (((PyInteger) a[1].__int__()).getValue()) {
326:
327:                        case Types.BIGINT:
328:                        case Types.BIT:
329:                        case Types.DECIMAL:
330:                        case Types.DOUBLE:
331:                        case Types.FLOAT:
332:                        case Types.INTEGER:
333:                        case Types.SMALLINT:
334:                            a[4] = column.__getitem__(Procedure.PRECISION);
335:                            a[5] = column.__getitem__(Procedure.SCALE);
336:                            break;
337:
338:                        default:
339:                            a[4] = Py.None;
340:                            a[5] = Py.None;
341:                            break;
342:                        }
343:
344:                        int nullable = ((PyInteger) column.__getitem__(
345:                                Procedure.NULLABLE).__int__()).getValue();
346:
347:                        a[6] = (nullable == DatabaseMetaData.procedureNullable) ? Py.One
348:                                : Py.Zero;
349:
350:                        ((PyList) metadata).append(new PyTuple(a));
351:                        break;
352:                    }
353:                }
354:
355:                return metadata;
356:            }
357:
358:            /**
359:             * Method createResults
360:             *
361:             * @param callableStatement
362:             * @param procedure
363:             * @param params
364:             * @return PyObject
365:             * @throws SQLException
366:             */
367:            protected PyObject createResults(
368:                    CallableStatement callableStatement, Procedure procedure,
369:                    PyObject params) throws SQLException {
370:
371:                PyList results = new PyList();
372:
373:                for (int i = 0, j = 0, len = procedure.columns.__len__(); i < len; i++) {
374:                    PyObject obj = Py.None;
375:                    PyObject column = procedure.columns.__getitem__(i);
376:                    int colType = ((PyInteger) column.__getitem__(
377:                            Procedure.COLUMN_TYPE).__int__()).getValue();
378:                    int dataType = ((PyInteger) column.__getitem__(
379:                            Procedure.DATA_TYPE).__int__()).getValue();
380:
381:                    switch (colType) {
382:
383:                    case DatabaseMetaData.procedureColumnIn:
384:                        j++;
385:                        break;
386:
387:                    case DatabaseMetaData.procedureColumnOut:
388:                    case DatabaseMetaData.procedureColumnInOut:
389:                        obj = datahandler.getPyObject(callableStatement, i + 1,
390:                                dataType);
391:
392:                        params.__setitem__(j++, obj);
393:                        break;
394:
395:                    case DatabaseMetaData.procedureColumnReturn:
396:                        obj = datahandler.getPyObject(callableStatement, i + 1,
397:                                dataType);
398:
399:                        // Oracle sends ResultSets as a return value
400:                        Object rs = obj.__tojava__(ResultSet.class);
401:
402:                        if (rs == Py.NoConversion) {
403:                            results.append(obj);
404:                        } else {
405:                            add((ResultSet) rs);
406:                        }
407:                        break;
408:                    }
409:                }
410:
411:                if (results.__len__() == 0) {
412:                    return results;
413:                }
414:
415:                PyList ret = new PyList();
416:
417:                ret.append(__builtin__.tuple(results));
418:
419:                return ret;
420:            }
421:
422:            /**
423:             * Creates the results of a query.  Iterates through the list and builds the tuple.
424:             *
425:             * @param set      result set
426:             * @param skipCols set of JDBC-indexed columns to automatically set to None
427:             * @return a list of tuples of the results
428:             * @throws SQLException
429:             */
430:            protected PyList createResults(ResultSet set, Set skipCols,
431:                    PyObject metaData) throws SQLException {
432:
433:                PyList res = new PyList();
434:
435:                while (set.next()) {
436:                    PyObject tuple = createResult(set, skipCols, metaData);
437:
438:                    res.append(tuple);
439:                }
440:
441:                return res;
442:            }
443:
444:            /**
445:             * Creates the individual result row from the current ResultSet row.
446:             *
447:             * @param set      result set
448:             * @param skipCols set of JDBC-indexed columns to automatically set to None
449:             * @return a tuple of the results
450:             * @throws SQLException
451:             */
452:            protected PyTuple createResult(ResultSet set, Set skipCols,
453:                    PyObject metaData) throws SQLException {
454:
455:                int descriptionLength = metaData.__len__();
456:                PyObject[] row = new PyObject[descriptionLength];
457:
458:                for (int i = 0; i < descriptionLength; i++) {
459:                    if ((skipCols != null)
460:                            && skipCols.contains(new Integer(i + 1))) {
461:                        row[i] = Py.None;
462:                    } else {
463:                        int type = ((PyInteger) metaData.__getitem__(i)
464:                                .__getitem__(1)).getValue();
465:
466:                        row[i] = datahandler.getPyObject(set, i + 1, type);
467:                    }
468:                }
469:
470:                SQLWarning warning = set.getWarnings();
471:
472:                if (warning != null) {
473:                    fireWarning(warning);
474:                }
475:
476:                PyTuple tuple = new PyTuple(row);
477:
478:                return tuple;
479:            }
480:
481:            protected void fireWarning(SQLWarning warning) {
482:
483:                WarningEvent event = new WarningEvent(this , warning);
484:
485:                for (int i = listeners.size() - 1; i >= 0; i--) {
486:                    try {
487:                        ((WarningListener) listeners.get(i)).warning(event);
488:                    } catch (Throwable t) {
489:                    }
490:                }
491:            }
492:
493:            public void addWarningListener(WarningListener listener) {
494:                this .listeners.add(listener);
495:            }
496:
497:            public boolean removeWarningListener(WarningListener listener) {
498:                return this .listeners.remove(listener);
499:            }
500:        }
501:
502:        /**
503:         * This version of fetch builds the results statically.  This consumes more resources but
504:         * allows for efficient closing of database resources because the contents of the result
505:         * set are immediately consumed.  It also allows for an accurate rowcount attribute, whereas
506:         * a dynamic query is unable to provide this information until all the results have been
507:         * consumed.
508:         */
509:        class StaticFetch extends Fetch {
510:
511:            /**
512:             * Field results
513:             */
514:            protected List results;
515:
516:            /**
517:             * Field descriptions
518:             */
519:            protected List descriptions;
520:
521:            /**
522:             * Construct a static fetch.  The entire result set is iterated as it
523:             * is added and the result set is immediately closed.
524:             */
525:            public StaticFetch(DataHandler datahandler) {
526:
527:                super (datahandler);
528:
529:                this .results = new LinkedList();
530:                this .descriptions = new LinkedList();
531:            }
532:
533:            /**
534:             * Method add
535:             *
536:             * @param resultSet
537:             */
538:            public void add(ResultSet resultSet) {
539:                this .add(resultSet, null);
540:            }
541:
542:            /**
543:             * Method add
544:             *
545:             * @param resultSet
546:             * @param skipCols
547:             */
548:            public void add(ResultSet resultSet, Set skipCols) {
549:
550:                try {
551:                    if ((resultSet != null)
552:                            && (resultSet.getMetaData() != null)) {
553:                        PyObject metadata = this .createDescription(resultSet
554:                                .getMetaData());
555:                        PyObject result = this .createResults(resultSet,
556:                                skipCols, metadata);
557:
558:                        this .results.add(result);
559:                        this .descriptions.add(metadata);
560:
561:                        // we want the rowcount of the first result set
562:                        this .rowcount = ((PyObject) this .results.get(0))
563:                                .__len__();
564:
565:                        // we want the description of the first result set
566:                        this .description = ((PyObject) this .descriptions.get(0));
567:
568:                        // set the current rownumber
569:                        this .rownumber = 0;
570:                    }
571:                } catch (PyException e) {
572:                    throw e;
573:                } catch (Throwable e) {
574:                    throw zxJDBC.makeException(e);
575:                } finally {
576:                    try {
577:                        resultSet.close();
578:                    } catch (Throwable e) {
579:                    }
580:                }
581:            }
582:
583:            /**
584:             * Method add
585:             *
586:             * @param callableStatement
587:             * @param procedure
588:             * @param params
589:             */
590:            public void add(CallableStatement callableStatement,
591:                    Procedure procedure, PyObject params) {
592:
593:                try {
594:                    PyObject result = this .createResults(callableStatement,
595:                            procedure, params);
596:
597:                    if (result.__len__() > 0) {
598:                        this .results.add(result);
599:                        this .descriptions
600:                                .add(this .createDescription(procedure));
601:
602:                        // we want the rowcount of the first result set
603:                        this .rowcount = ((PyObject) this .results.get(0))
604:                                .__len__();
605:
606:                        // we want the description of the first result set
607:                        this .description = ((PyObject) this .descriptions.get(0));
608:
609:                        // set the current rownumber
610:                        this .rownumber = 0;
611:                    }
612:                } catch (PyException e) {
613:                    throw e;
614:                } catch (Throwable e) {
615:                    throw zxJDBC.makeException(e);
616:                }
617:            }
618:
619:            /**
620:             * Fetch all (remaining) rows of a query result, returning them as a sequence
621:             * of sequences (e.g. a list of tuples). Note that the cursor's arraysize attribute
622:             * can affect the performance of this operation.
623:             * <p/>
624:             * An Error (or subclass) exception is raised if the previous call to executeXXX()
625:             * did not produce any result set or no call was issued yet.
626:             *
627:             * @return a sequence of sequences from the result set, or an empty sequence when
628:             *         no more data is available
629:             */
630:            public PyObject fetchall() {
631:                return fetchmany(this .rowcount);
632:            }
633:
634:            /**
635:             * Fetch the next set of rows of a query result, returning a sequence of
636:             * sequences (e.g. a list of tuples). An empty sequence is returned when
637:             * no more rows are available.
638:             * <p/>
639:             * The number of rows to fetch per call is specified by the parameter. If
640:             * it is not given, the cursor's arraysize determines the number of rows
641:             * to be fetched. The method should try to fetch as many rows as indicated
642:             * by the size parameter. If this is not possible due to the specified number
643:             * of rows not being available, fewer rows may be returned.
644:             * <p/>
645:             * An Error (or subclass) exception is raised if the previous call to executeXXX()
646:             * did not produce any result set or no call was issued yet.
647:             * <p/>
648:             * Note there are performance considerations involved with the size parameter.
649:             * For optimal performance, it is usually best to use the arraysize attribute.
650:             * If the size parameter is used, then it is best for it to retain the same value
651:             * from one fetchmany() call to the next.
652:             *
653:             * @return a sequence of sequences from the result set, or an empty sequence when
654:             *         no more data is available
655:             */
656:            public PyObject fetchmany(int size) {
657:
658:                if ((results == null) || (results.size() == 0)) {
659:                    throw zxJDBC.makeException(zxJDBC.DatabaseError,
660:                            "no results");
661:                }
662:
663:                PyObject res = new PyList();
664:                PyObject current = (PyObject) results.get(0);
665:
666:                if (size <= 0) {
667:                    size = this .rowcount;
668:                }
669:
670:                if (this .rownumber < this .rowcount) {
671:                    res = current.__getslice__(Py.newInteger(this .rownumber),
672:                            Py.newInteger(this .rownumber + size), Py.One);
673:                    this .rownumber += size;
674:                }
675:
676:                return res;
677:            }
678:
679:            /**
680:             * Method scroll
681:             *
682:             * @param value
683:             * @param mode  'relative' or 'absolute'
684:             */
685:            public void scroll(int value, String mode) {
686:
687:                int pos;
688:
689:                if ("relative".equals(mode)) {
690:                    pos = this .rownumber + value;
691:                } else if ("absolute".equals(mode)) {
692:                    pos = value;
693:                } else {
694:                    throw zxJDBC.makeException(zxJDBC.ProgrammingError,
695:                            "invalid cursor scroll mode [" + mode + "]");
696:                }
697:
698:                if ((pos >= 0) && (pos < this .rowcount)) {
699:                    this .rownumber = pos;
700:                } else {
701:                    throw zxJDBC.makeException(Py.IndexError, "cursor index ["
702:                            + pos + "] out of range");
703:                }
704:            }
705:
706:            /**
707:             * Move the result pointer to the next set if available.
708:             *
709:             * @return true if more sets exist, else None
710:             */
711:            public PyObject nextset() {
712:
713:                PyObject next = Py.None;
714:
715:                if ((results != null) && (results.size() > 1)) {
716:                    this .results.remove(0);
717:                    this .descriptions.remove(0);
718:
719:                    next = (PyObject) this .results.get(0);
720:                    this .description = (PyObject) this .descriptions.get(0);
721:                    this .rowcount = next.__len__();
722:                    this .rownumber = 0;
723:                }
724:
725:                return (next == Py.None) ? Py.None : Py.One;
726:            }
727:
728:            /**
729:             * Remove the results.
730:             */
731:            public void close() throws SQLException {
732:
733:                super .close();
734:
735:                this .rownumber = -1;
736:
737:                this .results.clear();
738:            }
739:        }
740:
741:        /**
742:         * Dynamically construct the results from an execute*().  The static version builds the entire
743:         * result set immediately upon completion of the query, however in some circumstances, this
744:         * requires far too many resources to be efficient.  In this version of the fetch the resources
745:         * remain constant.  The dis-advantage to this approach from an API perspective is its impossible
746:         * to generate an accurate rowcount since not all the rows have been consumed.
747:         */
748:        class DynamicFetch extends Fetch {
749:
750:            /**
751:             * Field skipCols
752:             */
753:            protected Set skipCols;
754:
755:            /**
756:             * Field resultSet
757:             */
758:            protected ResultSet resultSet;
759:
760:            /**
761:             * Construct a dynamic fetch.
762:             */
763:            public DynamicFetch(DataHandler datahandler) {
764:                super (datahandler);
765:            }
766:
767:            /**
768:             * Add the result set to the results.  If more than one result
769:             * set is attempted to be added, an Error is raised since JDBC
770:             * requires that only one ResultSet be iterated for one Statement
771:             * at any one time.  Since this is a dynamic iteration, it precludes
772:             * the addition of more than one result set.
773:             */
774:            public void add(ResultSet resultSet) {
775:                add(resultSet, null);
776:            }
777:
778:            /**
779:             * Add the result set to the results.  If more than one result
780:             * set is attempted to be added, an Error is raised since JDBC
781:             * requires that only one ResultSet be iterated for one Statement
782:             * at any one time.  Since this is a dynamic iteration, it precludes
783:             * the addition of more than one result set.
784:             */
785:            public void add(ResultSet resultSet, Set skipCols) {
786:
787:                if (this .resultSet != null) {
788:                    throw zxJDBC.makeException(zxJDBC
789:                            .getString("onlyOneResultSet"));
790:                }
791:
792:                try {
793:                    if ((resultSet != null)
794:                            && (resultSet.getMetaData() != null)) {
795:                        if (this .description == Py.None) {
796:                            this .description = this .createDescription(resultSet
797:                                    .getMetaData());
798:                        }
799:
800:                        this .resultSet = resultSet;
801:                        this .skipCols = skipCols;
802:
803:                        // it would be more compliant if we knew the resultSet actually
804:                        // contained some rows, but since we don't make a stab at it so
805:                        // everything else looks better
806:                        this .rowcount = 0;
807:                        this .rownumber = 0;
808:                    }
809:                } catch (PyException e) {
810:                    throw e;
811:                } catch (Throwable e) {
812:                    throw zxJDBC.makeException(e);
813:                }
814:            }
815:
816:            /**
817:             * Method add
818:             *
819:             * @param callableStatement
820:             * @param procedure
821:             * @param params
822:             */
823:            public void add(CallableStatement callableStatement,
824:                    Procedure procedure, PyObject params) {
825:                throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC
826:                        .getString("nocallprocsupport"));
827:            }
828:
829:            /**
830:             * Iterate the remaining contents of the ResultSet and return.
831:             */
832:            public PyObject fetchall() {
833:                return fetch(0, true);
834:            }
835:
836:            /**
837:             * Iterate up to size rows remaining in the ResultSet and return.
838:             */
839:            public PyObject fetchmany(int size) {
840:                return fetch(size, false);
841:            }
842:
843:            /**
844:             * Internal use only.  If <i>all</i> is true, return everything
845:             * that's left in the result set, otherwise return up to size.  Fewer
846:             * than size may be returned if fewer than size results are left in
847:             * the set.
848:             */
849:            private PyObject fetch(int size, boolean all) {
850:
851:                PyList res = new PyList();
852:
853:                if (this .resultSet == null) {
854:                    throw zxJDBC.makeException(zxJDBC.DatabaseError,
855:                            "no results");
856:                }
857:
858:                try {
859:                    all = (size < 0) ? true : all;
860:
861:                    while (((size-- > 0) || all) && this .resultSet.next()) {
862:                        PyTuple tuple = createResult(this .resultSet,
863:                                this .skipCols, this .description);
864:                        res.append(tuple);
865:                        this .rowcount++;
866:                        this .rownumber = this .resultSet.getRow();
867:                    }
868:                } catch (AbstractMethodError e) {
869:                    throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC
870:                            .getString("nodynamiccursors"));
871:                } catch (PyException e) {
872:                    throw e;
873:                } catch (Throwable e) {
874:                    throw zxJDBC.makeException(e);
875:                }
876:
877:                return res;
878:            }
879:
880:            /**
881:             * Always returns None.
882:             */
883:            public PyObject nextset() {
884:                return Py.None;
885:            }
886:
887:            /**
888:             * Method scroll
889:             *
890:             * @param value
891:             * @param mode
892:             */
893:            public void scroll(int value, String mode) {
894:
895:                try {
896:                    int type = this .resultSet.getType();
897:
898:                    if ((type != ResultSet.TYPE_FORWARD_ONLY) || (value > 0)) {
899:                        if ("relative".equals(mode)) {
900:                            if (value < 0) {
901:                                value = Math.abs(this .rownumber + value);
902:                            } else if (value > 0) {
903:                                value = this .rownumber + value + 1;
904:                            }
905:                        } else if ("absolute".equals(mode)) {
906:                            if (value < 0) {
907:                                throw zxJDBC.makeException(Py.IndexError,
908:                                        "cursor index [" + value
909:                                                + "] out of range");
910:                            }
911:                        } else {
912:                            throw zxJDBC
913:                                    .makeException(zxJDBC.ProgrammingError,
914:                                            "invalid cursor scroll mode ["
915:                                                    + mode + "]");
916:                        }
917:
918:                        if (value == 0) {
919:                            this .resultSet.beforeFirst();
920:                        } else {
921:                            if (!this .resultSet.absolute(value)) {
922:                                throw zxJDBC.makeException(Py.IndexError,
923:                                        "cursor index [" + value
924:                                                + "] out of range");
925:                            }
926:                        }
927:
928:                        // since .rownumber is the *next* row, then the JDBC value suits us fine
929:                        this .rownumber = this .resultSet.getRow();
930:                    } else {
931:                        String msg = "dynamic result set of type [" + type
932:                                + "] does not support scrolling";
933:
934:                        throw zxJDBC.makeException(zxJDBC.NotSupportedError,
935:                                msg);
936:                    }
937:                } catch (AbstractMethodError e) {
938:                    throw zxJDBC.makeException(zxJDBC.NotSupportedError, zxJDBC
939:                            .getString("nodynamiccursors"));
940:                } catch (SQLException e) {
941:                    throw zxJDBC.makeException(e);
942:                } catch (Throwable t) {
943:                    throw zxJDBC.makeException(t);
944:                }
945:            }
946:
947:            /**
948:             * Close the underlying ResultSet.
949:             */
950:            public void close() throws SQLException {
951:
952:                super .close();
953:
954:                if (this .resultSet == null) {
955:                    return;
956:                }
957:
958:                this .rownumber = -1;
959:
960:                try {
961:                    this.resultSet.close();
962:                } finally {
963:                    this.resultSet = null;
964:                }
965:            }
966:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.