001: /*
002: * Jython Database Specification API 2.0
003: *
004: * $Id: DBSource.java 2414 2005-02-23 04:26:23Z bzimmer $
005: *
006: * Copyright (c) 2001 brian zimmer <bzimmer@ziclix.com>
007: *
008: */
009: package com.ziclix.python.sql.pipe.db;
010:
011: import com.ziclix.python.sql.PyConnection;
012: import com.ziclix.python.sql.pipe.Source;
013: import org.python.core.Py;
014: import org.python.core.PyObject;
015: import org.python.core.PyTuple;
016:
017: /**
018: * A database source. Given a PyConnection and information about the query, produce the data.
019: *
020: * @author brian zimmer
021: * @version $Revision: 2414 $
022: */
023: public class DBSource extends BaseDB implements Source {
024:
025: /**
026: * Field sql
027: */
028: protected String sql;
029:
030: /**
031: * Field sentHeader
032: */
033: protected boolean sentHeader;
034:
035: /**
036: * Field params, include
037: */
038: protected PyObject params, include;
039:
040: /**
041: * Constructor for handling the generation of data.
042: *
043: * @param connection the database connection
044: * @param dataHandler a custom DataHandler for the cursor, can be None
045: * @param tableName the table in question on the source database
046: * @param where an optional where clause, defaults to '(1=1)' if null
047: * @param include the columns to be queried from the source, '*' if None
048: * @param params optional params to substituted in the where clause
049: */
050: public DBSource(PyConnection connection, Class dataHandler,
051: String tableName, String where, PyObject include,
052: PyObject params) {
053:
054: super (connection, dataHandler, tableName);
055:
056: this .params = params;
057: this .include = include;
058: this .sentHeader = false;
059: this .sql = this .createSql(where);
060: }
061:
062: /**
063: * Create the sql string given the where clause.
064: */
065: protected String createSql(String where) {
066:
067: // create the sql statement, using the columns if available
068: StringBuffer sb = new StringBuffer("select ");
069:
070: if ((this .include == Py.None) || (this .include.__len__() == 0)) {
071: sb.append("*");
072: } else {
073: for (int i = 1; i < this .include.__len__(); i++) {
074: sb.append(this .include.__getitem__(i)).append(",");
075: }
076:
077: sb.append(this .include
078: .__getitem__(this .include.__len__() - 1));
079: }
080:
081: sb.append(" from ").append(this .tableName);
082: sb.append(" where ").append((where == null) ? "(1=1)" : where);
083:
084: String sql = sb.toString();
085:
086: return sql;
087: }
088:
089: /**
090: * Return the next row in the result set. The first row returned will be column information.
091: */
092: public PyObject next() {
093:
094: if (this .sentHeader) {
095:
096: // Py.None will be sent when all done, so this will close down the queue
097: return this .cursor.fetchone();
098: } else {
099: this .cursor.execute(Py.newString(this .sql), this .params,
100: Py.None, Py.None);
101:
102: PyObject description = this .cursor
103: .__findattr__("description");
104:
105: // we can't insert if we don't know column names
106: if ((description == Py.None)
107: || (description.__len__() == 0)) {
108:
109: // let the destination worry about handling the empty set
110: return Py.None;
111: }
112:
113: int len = description.__len__();
114: PyObject[] columns = new PyObject[len];
115:
116: for (int i = 0; i < len; i++) {
117: PyObject[] colInfo = new PyObject[2];
118:
119: // col name
120: colInfo[0] = description.__getitem__(i).__getitem__(0);
121:
122: // col type
123: colInfo[1] = description.__getitem__(i).__getitem__(1);
124: columns[i] = new PyTuple(colInfo);
125: }
126:
127: PyObject row = new PyTuple(columns);
128:
129: Py.writeDebug("db-source", row.toString());
130:
131: this .sentHeader = true;
132:
133: return row;
134: }
135: }
136:
137: /**
138: * Method start
139: */
140: public void start() {
141: }
142:
143: /**
144: * Close the cursor.
145: */
146: public void end() {
147:
148: if (this.cursor != null) {
149: this.cursor.close();
150: }
151: }
152: }
|