001: //
002: // Copyright 1998 CDS Networks, Inc., Medford Oregon
003: //
004: // All rights reserved.
005: //
006: // Redistribution and use in source and binary forms, with or without
007: // modification, are permitted provided that the following conditions are met:
008: // 1. Redistributions of source code must retain the above copyright
009: // notice, this list of conditions and the following disclaimer.
010: // 2. Redistributions in binary form must reproduce the above copyright
011: // notice, this list of conditions and the following disclaimer in the
012: // documentation and/or other materials provided with the distribution.
013: // 3. All advertising materials mentioning features or use of this software
014: // must display the following acknowledgement:
015: // This product includes software developed by CDS Networks, Inc.
016: // 4. The name of CDS Networks, Inc. may not be used to endorse or promote
017: // products derived from this software without specific prior
018: // written permission.
019: //
020: // THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
021: // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: // ARE DISCLAIMED. IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
024: // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
025: // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
026: // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
027: // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
028: // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
029: // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
030: // SUCH DAMAGE.
031: //
032:
033: /**
034: * A Statement object is used for executing a static SQL statement and
035: * obtaining the results produced by it.
036: *
037: * <p>Only one ResultSet per Statement can be open at any point in time.
038: * Therefore, if the reading of one ResultSet is interleaved with the
039: * reading of another, each must have been generated by different
040: * Statements. All statement execute methods implicitly close a
041: * statement's current ResultSet if an open one exists.
042: *
043: * @see java.sql.Statement
044: * @see ResultSet
045: * @version $Id: Statement.java,v 1.1 2007-10-19 13:23:55 sinisa Exp $
046: */package com.internetcds.jdbc.tds;
047:
048: import java.sql.*;
049:
050: public class Statement implements java.sql.Statement {
051: public static final String cvsVersion = "$Id: Statement.java,v 1.1 2007-10-19 13:23:55 sinisa Exp $";
052:
053: private java.sql.Connection connection; // The connection who created us
054: // ResultSet currentResults = null; // The current results
055: protected SQLWarningChain warningChain; // The warnings chain.
056: protected int timeout = 0; // The timeout for a query
057:
058: protected Tds tds = null;
059:
060: protected java.sql.ResultSet results = null;
061: private java.sql.ResultSetMetaData metaResults = null;
062:
063: private boolean escapeProcessing = true;
064:
065: protected int updateCount = -1;
066:
067: private int maxFieldSize = (1 << 31) - 1;
068: private int maxRows = 0;
069: private boolean isClosed = false;
070:
071: /**
072: * Constructor for a Statement. It simply sets the connection
073: * that created us.
074: *
075: * @param connection_ the Connection instantation that creates us
076: * @param tds_ a TDS instance to use for communication with server.
077: */
078: public Statement(Object connection_, Tds tds_) throws SQLException {
079: tds = tds_;
080: connection = (java.sql.Connection) connection_;
081: warningChain = new SQLWarningChain();
082: }
083:
084: private void NotImplemented() throws java.sql.SQLException {
085: throw new SQLException("Not Implemented");
086: }
087:
088: protected void finalize() throws Throwable {
089: super .finalize();
090:
091: if (tds != null) {
092: close();
093: }
094: }
095:
096: /**
097: * Execute a SQL statement that retruns a single ResultSet
098: *
099: * @param Sql typically a static SQL SELECT statement
100: * @return a ResulSet that contains the data produced by the query
101: * @exception SQLException if a database access error occurs
102: */
103: public java.sql.ResultSet executeQuery(String sql)
104: throws SQLException {
105:
106: if (execute(sql)) {
107: startResultSet();
108: }
109:
110: return results;
111: }
112:
113: /**
114: * Execute a SQL INSERT, UPDATE or DELETE statement. In addition
115: * SQL statements that return nothing such as SQL DDL statements
116: * can be executed
117: *
118: * Any IDs generated for AUTO_INCREMENT fields can be retrieved
119: * by looking through the SQLWarning chain of this statement
120: * for warnings of the form "LAST_INSERTED_ID = 'some number',
121: * COMMAND = 'your sql'".
122: *
123: * @param Sql a SQL statement
124: * @return either a row count, or 0 for SQL commands
125: * @exception SQLException if a database access error occurs
126: */
127:
128: public int executeUpdate(String sql) throws SQLException {
129: if (execute(sql)) {
130: startResultSet();
131: closeResults();
132: throw new SQLException(
133: "executeUpdate can't return a result set");
134: } else {
135: return getUpdateCount();
136: }
137: }
138:
139: protected void closeResults() throws java.sql.SQLException {
140:
141: if (results != null) {
142: results.close();
143: results = null;
144: }
145: }
146:
147: private void skipToEnd() throws java.sql.SQLException,
148: java.io.IOException,
149: com.internetcds.jdbc.tds.TdsUnknownPacketSubType,
150: com.internetcds.jdbc.tds.TdsException {
151: boolean done;
152: PacketResult tmp;
153:
154: do {
155: tmp = tds.processSubPacket();
156: done = (tmp instanceof PacketEndTokenResult)
157: && (!((PacketEndTokenResult) tmp).moreResults());
158: } while (!done);
159: }
160:
161: public void commit() throws java.sql.SQLException,
162: java.io.IOException,
163: com.internetcds.jdbc.tds.TdsUnknownPacketSubType,
164: com.internetcds.jdbc.tds.TdsException {
165: String sql = "IF @@TRANCOUNT > 0 COMMIT TRAN ";
166:
167: if (tds == null) {
168: throw new SQLException("Statement is closed");
169: }
170:
171: executeQuery(sql);
172: skipToEnd();
173: }
174:
175: public void rollback() throws java.sql.SQLException,
176: java.io.IOException,
177: com.internetcds.jdbc.tds.TdsUnknownPacketSubType,
178: com.internetcds.jdbc.tds.TdsException {
179: String sql = "IF @@TRANCOUNT > 0 ROLLBACK TRAN ";
180:
181: if (tds == null) {
182: throw new SQLException("Statement is closed");
183: }
184:
185: executeQuery(sql);
186: skipToEnd();
187: }
188:
189: /**
190: * In many cases, it is desirable to immediately release a
191: * Statement's database and JDBC resources instead of waiting
192: * for this to happen when it is automatically closed. The
193: * close method provides this immediate release.
194: *
195: * <p><B>Note:</B> A Statement is automatically closed when it is
196: * garbage collected. When a Statement is closed, its current
197: * ResultSet, if one exists, is also closed.
198: *
199: * @exception SQLException if a database access error occurs (why?)
200: */
201: public void close() throws SQLException {
202: closeResults();
203:
204: // Rollback any pending transactions
205: /* try
206: {
207: rollback();
208: }
209: catch (com.internetcds.jdbc.tds.TdsUnknownPacketSubType e)
210: {
211: throw new SQLException("Unknown packet. \n" + e.getMessage());
212: }
213: catch (com.internetcds.jdbc.tds.TdsException e)
214: {
215: // XXX
216: // ignore this for now
217: }
218: catch (java.io.IOException e)
219: {
220: // XXX
221: // ignore this for now
222: }
223:
224: */
225: // now we need to relinquish the connection
226: if (tds != null) {
227: Tds tmpTds = tds;
228: tds = null;
229: try {
230: ((ConnectionHelper) connection).relinquish(tmpTds);
231: } catch (TdsException e) {
232: throw new SQLException("Internal Error: "
233: + e.getMessage());
234: }
235: }
236: try {
237: ((ConnectionHelper) connection).markAsClosed(this );
238: } catch (TdsException e) {
239: throw new SQLException(e.getMessage());
240: }
241: this .isClosed = true;
242:
243: }
244:
245: /**
246: * The maxFieldSize limit (in bytes) is the maximum amount of
247: * data returned for any column value; it only applies to
248: * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
249: * columns. If the limit is exceeded, the excess data is silently
250: * discarded.
251: *
252: * @return the current max column size limit; zero means unlimited
253: * @exception SQLException if a database access error occurs
254: */
255:
256: public int getMaxFieldSize() throws SQLException {
257: return maxFieldSize;
258: }
259:
260: /**
261: * Sets the maxFieldSize
262: *
263: * @param max the new max column size limit; zero means unlimited
264: * @exception SQLException if size exceeds buffer size
265: */
266:
267: public void setMaxFieldSize(int max) throws SQLException {
268: maxFieldSize = max;
269: }
270:
271: /**
272: * The maxRows limit is set to limit the number of rows that
273: * any ResultSet can contain. If the limit is exceeded, the
274: * excess rows are silently dropped.
275: *
276: * @return the current maximum row limit; zero means unlimited
277: * @exception SQLException if a database access error occurs
278: */
279:
280: public int getMaxRows() throws SQLException {
281: return maxRows;
282: }
283:
284: /**
285: * Set the maximum number of rows
286: *
287: * @param max the new max rows limit; zero means unlimited
288: * @exception SQLException if a database access error occurs
289: * @see getMaxRows
290: */
291:
292: public void setMaxRows(int max) throws SQLException {
293: if (maxRows < 0) {
294: throw new SQLException("Negative row count");
295: }
296: maxRows = max;
297:
298: this .executeUpdate("set rowcount " + maxRows);
299: }
300:
301: /**
302: * If escape scanning is on (the default), the driver will do escape
303: * substitution before sending the SQL to the database.
304: *
305: * @param enable true to enable; false to disable
306: * @exception SQLException if a database access error occurs
307: */
308:
309: public void setEscapeProcessing(boolean enable) throws SQLException {
310: escapeProcessing = enable;
311: }
312:
313: /**
314: * The queryTimeout limit is the number of seconds the driver
315: * will wait for a Statement to execute. If the limit is
316: * exceeded, a SQLException is thrown.
317: *
318: * @return the current query timeout limit in seconds; 0 = unlimited
319: * @exception SQLException if a database access error occurs
320: */
321:
322: public int getQueryTimeout() throws SQLException {
323: return timeout;
324: }
325:
326: /**
327: * Sets the queryTimeout limit
328: *
329: * @param seconds - the new query timeout limit in seconds
330: * @exception SQLException if a database access error occurs
331: */
332:
333: public void setQueryTimeout(int seconds) throws SQLException {
334: timeout = seconds;
335: }
336:
337: /**
338: *
339: * @exception SQLException
340: */
341: public void cancel() throws SQLException {
342: if (tds == null) {
343: throw new SQLException("Statement is closed");
344: }
345:
346: try {
347: tds.cancel();
348: } catch (com.internetcds.jdbc.tds.TdsException e) {
349: throw new SQLException(e.getMessage());
350: } catch (java.io.IOException e) {
351: throw new SQLException(e.getMessage());
352: }
353: }
354:
355: /**
356: * The first warning reported by calls on this Statement is
357: * returned. A Statement's execute methods clear its SQLWarning
358: * chain. Subsequent Statement warnings will be chained to this
359: * SQLWarning.
360: *
361: * <p>The Warning chain is automatically cleared each time a statement
362: * is (re)executed.
363: *
364: * <p><B>Note:</B> If you are processing a ResultSet then any warnings
365: * associated with ResultSet reads will be chained on the ResultSet
366: * object.
367: *
368: * @return the first SQLWarning on null
369: * @exception SQLException if a database access error occurs
370: */
371: public SQLWarning getWarnings() throws SQLException {
372: return warningChain.getWarnings();
373: }
374:
375: /**
376: * After this call, getWarnings returns null until a new warning
377: * is reported for this Statement.
378: *
379: * @exception SQLException if a database access error occurs (why?)
380: */
381: public void clearWarnings() throws SQLException {
382: warningChain.clearWarnings();
383: }
384:
385: /**
386: * setCursorName defines the SQL cursor name that will be used by
387: * subsequent execute methods. This name can then be used in SQL
388: * positioned update/delete statements to identify the current row
389: * in the ResultSet generated by this statement. If a database
390: * doesn't support positioned update/delete, this method is a
391: * no-op.
392: *
393: *
394: * @param name the new cursor name
395: * @exception SQLException if a database access error occurs
396: */
397: public void setCursorName(String name) throws SQLException {
398: NotImplemented();
399: }
400:
401: /**
402: * @param sql any SQL statement
403: * @return true if the next result is a ResulSet, false if it is
404: * an update count or there are no more results
405: * @exception SQLException if a database access error occurs
406: */
407: public boolean execute(String sql) throws SQLException {
408:
409: SQLException exception = null;
410:
411: if (tds == null) {
412: throw new SQLException("Statement is closed");
413: }
414:
415: closeResults();
416: clearWarnings();
417: updateCount = -1;
418: try {
419: if (escapeProcessing) {
420: sql = Tds.toNativeSql(sql, tds.getServerType());
421: }
422: tds.executeQuery(sql, this , timeout);
423: } catch (java.io.IOException e) {
424: throw new SQLException("Network error- " + e.getMessage());
425: } catch (com.internetcds.jdbc.tds.TdsException e) {
426: throw new SQLException("TDS error- " + e.getMessage());
427: }
428: return getMoreResults();
429: } // execute()
430:
431: /**
432: * getResultSet returns the current result as a ResultSet. It
433: * should only be called once per result.
434: *
435: * @return the current result set; null if there are no more
436: * @exception SQLException if a database access error occurs
437: */
438: public java.sql.ResultSet getResultSet() throws SQLException {
439: try {
440: if (tds == null) {
441: throw new SQLException("Statement is closed");
442: }
443: closeResults();
444:
445: if (tds.peek() == TdsDefinitions.TDS_DONEINPROC) {
446: PacketResult tmp = tds.processSubPacket();
447: }
448:
449: if (tds.isResultSet()) // JJ 1999-01-09 used be: ;getMoreResults())
450: {
451: startResultSet();
452: } else if (updateCount != -1) {
453: if (!tds.isEndOfResults()) {
454: // XXX
455: throw new SQLException("Internal error. "
456: + " expected EndOfResults, found 0x"
457: + Integer.toHexString(tds.peek() & 0xff));
458: }
459: PacketEndTokenResult end = (PacketEndTokenResult) tds
460: .processSubPacket();
461: updateCount = end.getRowCount();
462: results = null;
463: } else {
464: // We didn't have more data and we didn't have an update count,
465: // now what?
466: throw new SQLException("Internal error. Confused");
467: }
468: } catch (java.io.IOException e) {
469: throw new SQLException(e.getMessage());
470: } catch (TdsException e) {
471: throw new SQLException(e.getMessage());
472: }
473:
474: return results;
475: }
476:
477: /**
478: * getUpdateCount returns the current result as an update count,
479: * if the result is a ResultSet or there are no more results, -1
480: * is returned. It should only be called once per result.
481: *
482: * @return the current result as an update count.
483: * @exception SQLException if a database access error occurs
484: */
485: public int getUpdateCount() throws SQLException {
486: // if (updateCount == -1)
487: // {
488: // throw new SQLException("Don't have a count yet.");
489: // }
490: // XXX This isn't correct. We need to check to see if
491: // the result was a result set or if there are no more results.
492: // If either of those are true we are supposed to return -1
493: return updateCount;
494: }
495:
496: /**
497: * getMoreResults moves to a Statement's next result. If it returns
498: * true, this result is a ResulSet.
499: *
500: * @return true if the next ResultSet is valid
501: * @exception SQLException if a database access error occurs
502: */
503: public boolean getMoreResults() throws SQLException {
504: SQLException exception = null;
505: if (tds == null) {
506: throw new SQLException("Statement is closed");
507: }
508:
509: updateCount = -1; // Do we need this global variable?
510:
511: if (!tds.moreResults()) {
512: return false;
513: }
514:
515: closeResults(); // Reset all internal variables (why is this done here?)
516:
517: try {
518: tds.isResultSet();
519:
520: // Keep eating garbage and warnings until we reach the next result
521: while (!tds.isResultSet() && !tds.isEndOfResults()) {
522: if (tds.isProcId()) {
523: tds.processSubPacket();
524: } else if (tds.isDoneInProc()) {
525: PacketDoneInProcResult tmp = (PacketDoneInProcResult) tds
526: .processSubPacket();
527: } else if (tds.isTextUpdate()) {
528: PacketResult tmp1 = (PacketResult) tds
529: .processSubPacket();
530: } else if (tds.isMessagePacket() || tds.isErrorPacket()) {
531: PacketMsgResult tmp = (PacketMsgResult) tds
532: .processSubPacket();
533: exception = warningChain.addOrReturn(tmp);
534: } else if (tds.isReturnStatus()) {
535: tds.processSubPacket();
536: // skipToEnd();
537: } else {
538: throw new SQLException("Protocol confusion. "
539: + "Got a 0x"
540: + Integer.toHexString((tds.peek() & 0xff))
541: + " packet");
542: }
543: } // end while
544:
545: if (exception != null) {
546: try {
547: tds.discardResultSet(null);
548: } catch (java.io.IOException e) {
549: throw new SQLException(
550: "Error discarding result set while processing sql error- "
551: + exception.getMessage()
552: + "\nIOException was "
553: + e.getMessage());
554: } catch (com.internetcds.jdbc.tds.TdsException e) {
555: throw new SQLException(
556: "Error discarding result set while processing sql error- "
557: + exception.getMessage()
558: + "\nIOException was "
559: + e.getMessage());
560: }
561: throw exception;
562: }
563:
564: if (tds.isEndOfResults()) {
565: PacketEndTokenResult end = (PacketEndTokenResult) tds
566: .processSubPacket();
567: updateCount = end.getRowCount();
568: return false;
569:
570: } else if (tds.isResultSet()) {
571: return true;
572: } else {
573: throw new SQLException("Protocol confusion. "
574: + "Got a 0x"
575: + Integer.toHexString((tds.peek() & 0xff))
576: + " packet");
577: }
578: }
579:
580: catch (java.io.IOException e) {
581: throw new SQLException("Network error- " + e.getMessage());
582: } catch (com.internetcds.jdbc.tds.TdsException e) {
583: throw new SQLException("TDS error- " + e.getMessage());
584: }
585: }
586:
587: protected void startResultSet() throws SQLException {
588:
589: Columns names = null;
590: Columns info = null;
591: SQLException exception = null;
592:
593: try {
594: while (!tds.isResultRow() && !tds.isEndOfResults()) {
595: PacketResult tmp = tds.processSubPacket();
596:
597: if (tmp.getPacketType() == TdsDefinitions.TDS_DONEINPROC) {
598: // XXX We should do something with the possible ret_stat
599: } else if (tmp instanceof PacketColumnNamesResult) {
600: names = ((PacketColumnNamesResult) tmp)
601: .getColumnNames();
602: } else if (tmp instanceof PacketColumnInfoResult) {
603: info = ((PacketColumnInfoResult) tmp)
604: .getColumnInfo();
605: } else if (tmp instanceof PacketColumnOrderResult) {
606: // nop
607: // XXX do we want to do anything with this
608: } else if (tmp instanceof PacketTabNameResult) {
609: // nop
610: // XXX What should be done with this information?
611: } else if (tmp instanceof PacketControlResult) {
612: // nop
613: // XXX do we want to do anything with this
614: } else if (tmp instanceof PacketMsgResult) {
615: exception = warningChain
616: .addOrReturn((PacketMsgResult) tmp);
617: } else if (tmp instanceof PacketUnknown) {
618: // XXX Need to add to the warning chain
619: } else {
620: throw new SQLException(
621: "Trying to get a result set. Found a "
622: + tmp.getClass().getName());
623: }
624: }
625:
626: if (exception != null) {
627: throw exception;
628: } else if (!tds.isResultRow() && !tds.isEndOfResults()) {
629: // XXX
630: throw new SQLException(
631: "Confused. Was expecting a result row. "
632: + "Got a 0x"
633: + Integer
634: .toHexString(tds.peek() & 0xff));
635: }
636:
637: // TDS 7.0 includes everything in one subpacket.
638: if (info != null)
639: names.merge(info);
640: results = Constructors.newResultSet(tds, this , names);
641: } catch (com.internetcds.jdbc.tds.TdsException e) {
642: e.printStackTrace();
643: throw new SQLException(e.getMessage());
644: } catch (java.io.IOException e) {
645: e.printStackTrace();
646: throw new SQLException(e.getMessage());
647: }
648: }
649:
650: //--------------------------JDBC 2.0-----------------------------
651:
652: /**
653: * JDBC 2.0
654: *
655: * Gives the driver a hint as to the direction in which
656: * the rows in a result set
657: * will be processed. The hint applies only to result sets created
658: * using this Statement object. The default value is
659: * ResultSet.FETCH_FORWARD.
660: * <p>Note that this method sets the default fetch direction for
661: * result sets generated by this <code>Statement</code> object.
662: * Each result set has its own methods for getting and setting
663: * its own fetch direction.
664: * @param direction the initial direction for processing rows
665: * @exception SQLException if a database access error occurs
666: * or the given direction
667: * is not one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
668: * ResultSet.FETCH_UNKNOWN
669: */
670: public void setFetchDirection(int direction) throws SQLException {
671: NotImplemented();
672: }
673:
674: /**
675: * JDBC 2.0
676: *
677: * Retrieves the direction for fetching rows from
678: * database tables that is the default for result sets
679: * generated from this <code>Statement</code> object.
680: * If this <code>Statement</code> object has not set
681: * a fetch direction by calling the method <code>setFetchDirection</code>,
682: * the return value is implementation-specific.
683: *
684: * @return the default fetch direction for result sets generated
685: * from this <code>Statement</code> object
686: * @exception SQLException if a database access error occurs
687: */
688: public int getFetchDirection() throws SQLException {
689: NotImplemented();
690: return 0;
691: }
692:
693: /**
694: * JDBC 2.0
695: *
696: * Gives the JDBC driver a hint as to the number of rows that should
697: * be fetched from the database when more rows are needed. The number
698: * of rows specified affects only result sets created using this
699: * statement. If the value specified is zero, then the hint is ignored.
700: * The default value is zero.
701: *
702: * @param rows the number of rows to fetch
703: * @exception SQLException if a database access error occurs, or the
704: * condition 0 <= rows <= this.getMaxRows() is not satisfied.
705: */
706: public void setFetchSize(int rows) throws SQLException {
707: NotImplemented();
708: }
709:
710: /**
711: * JDBC 2.0
712: *
713: * Retrieves the number of result set rows that is the default
714: * fetch size for result sets
715: * generated from this <code>Statement</code> object.
716: * If this <code>Statement</code> object has not set
717: * a fetch size by calling the method <code>setFetchSize</code>,
718: * the return value is implementation-specific.
719: * @return the default fetch size for result sets generated
720: * from this <code>Statement</code> object
721: * @exception SQLException if a database access error occurs
722: */
723: public int getFetchSize() throws SQLException {
724: NotImplemented();
725: return 0;
726: }
727:
728: /**
729: * JDBC 2.0
730: *
731: * Retrieves the result set concurrency.
732: */
733: public int getResultSetConcurrency() throws SQLException {
734: NotImplemented();
735: return 0;
736: }
737:
738: /**
739: * JDBC 2.0
740: *
741: * Determine the result set type.
742: */
743: public int getResultSetType() throws SQLException {
744: NotImplemented();
745: return 0;
746: }
747:
748: /**
749: * JDBC 2.0
750: *
751: * Adds a SQL command to the current batch of commmands for the statement.
752: * This method is optional.
753: *
754: * @param sql typically this is a static SQL INSERT or UPDATE statement
755: * @exception SQLException if a database access error occurs, or the
756: * driver does not support batch statements
757: */
758: public void addBatch(String sql) throws SQLException {
759: NotImplemented();
760: }
761:
762: /**
763: * JDBC 2.0
764: *
765: * Makes the set of commands in the current batch empty.
766: * This method is optional.
767: *
768: * @exception SQLException if a database access error occurs or the
769: * driver does not support batch statements
770: */
771: public void clearBatch() throws SQLException {
772: NotImplemented();
773: }
774:
775: /**
776: * JDBC 2.0
777: *
778: * Submits a batch of commands to the database for execution.
779: * This method is optional.
780: *
781: * @return an array of update counts containing one element for each
782: * command in the batch. The array is ordered according
783: * to the order in which commands were inserted into the batch.
784: * @exception SQLException if a database access error occurs or the
785: * driver does not support batch statements
786: */
787: public int[] executeBatch() throws SQLException {
788: NotImplemented();
789: return null;
790: }
791:
792: /**
793: * JDBC 2.0
794: *
795: * Returns the <code>Connection</code> object
796: * that produced this <code>Statement</code> object.
797: * @return the connection that produced this statement
798: * @exception SQLException if a database access error occurs
799: */
800: public java.sql.Connection getConnection() throws SQLException {
801: return connection;
802: }
803:
804: //---------------------------------------------------------------------
805: // JDBC 3.0
806: //---------------------------------------------------------------------
807:
808: public boolean getMoreResults(int current) throws SQLException {
809: throw new UnsupportedOperationException(
810: "Statement.getMoreResults(int) unsupported");
811: }
812:
813: public ResultSet getGeneratedKeys() throws SQLException {
814: throw new UnsupportedOperationException(
815: "Statement.getGeneratedKeys() unsupported");
816: }
817:
818: public int executeUpdate(String sql, int autoGeneratedKeys)
819: throws SQLException {
820: throw new UnsupportedOperationException(
821: "Statement.executeUpdate(String,int) unsupported");
822: }
823:
824: public int executeUpdate(String sql, int[] columnIndexes)
825: throws SQLException {
826: throw new UnsupportedOperationException(
827: "Statement.executeUpdate(String,int[]) unsupported");
828: }
829:
830: public int executeUpdate(String sql, String[] columnNames)
831: throws SQLException {
832: throw new UnsupportedOperationException(
833: "Statement.executeUpdate(String,String[]) unsupported");
834: }
835:
836: public boolean execute(String sql, int autoGeneratedKeys)
837: throws SQLException {
838: throw new UnsupportedOperationException(
839: "Statement.execute(String,int) unsupported");
840: }
841:
842: public boolean execute(String sql, int[] columnIndexes)
843: throws SQLException {
844: throw new UnsupportedOperationException(
845: "Statement.execute(String,int[]) unsupported");
846: }
847:
848: public boolean execute(String sql, String[] columnNames)
849: throws SQLException {
850: throw new UnsupportedOperationException(
851: "Statement.execute(String,String[]) unsupported");
852: }
853:
854: public int getResultSetHoldability() throws SQLException {
855: throw new UnsupportedOperationException(
856: "Statement.getResultSetHoldability() unsupported");
857: }
858:
859: static public void main(String args[])
860: throws java.lang.ClassNotFoundException,
861: java.lang.IllegalAccessException,
862: java.lang.InstantiationException, SQLException {
863:
864: String query = null;
865:
866: String url = url = "" + "jdbc:freetds:" + "//" + "kap" + "/"
867: + "pubs";
868:
869: Class.forName("com.internetcds.jdbc.tds.Driver").newInstance();
870: java.sql.Connection connection;
871: connection = DriverManager.getConnection(url, "testuser",
872: "password");
873: java.sql.Statement stmt = connection.createStatement();
874:
875: query = ""
876: + "update titles "
877: + " set price=price+1.00 "
878: + " where title_id='MC3021' or title_id = 'BU1032' ";
879: int count = stmt.executeUpdate(query);
880: System.out.println("Updated " + count + " rows.");
881:
882: query = ""
883: + "select price, title_id, title, price*ytd_sales gross from titles"
884: + " where title like 'The%'";
885: java.sql.ResultSet rs = stmt.executeQuery(query);
886:
887: while (rs.next()) {
888: float price = rs.getFloat("price");
889: if (rs.wasNull()) {
890: System.out.println("price: null");
891: } else {
892: System.out.println("price: " + price);
893: }
894:
895: String title_id = rs.getString("title_id");
896: String title = rs.getString("title");
897: float gross = rs.getFloat("gross");
898:
899: System.out.println("id: " + title_id);
900: System.out.println("name: " + title);
901: System.out.println("gross: " + gross);
902: System.out.println("");
903: }
904: }
905:
906: public boolean isClosed() {
907: return isClosed;
908: }
909:
910: public boolean isPoolable() throws SQLException {
911: // TODO Auto-generated method stub
912: return false;
913: }
914:
915: public void setPoolable(boolean poolable) throws SQLException {
916: // TODO Auto-generated method stub
917: throw new UnsupportedOperationException(
918: "Statement.setPoolable(boolean) unsupported");
919:
920: }
921:
922: public boolean isWrapperFor(Class<?> iface) throws SQLException {
923: // TODO Auto-generated method stub
924: return false;
925: }
926:
927: public <T> T unwrap(Class<T> iface) throws SQLException {
928: // TODO Auto-generated method stub
929: return null;
930: }
931:
932: }
|